You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
T extends unknown is observably-different from an unconstrained T #61242
typeExample<T>=Textends{} ? keyofT : stringconstunknownConstraint=<Textendsunknown>(x: Example<T>): string=>xconstnoConstraint=<T>(x: Example<T>): string=>x// ^// Type 'string | number | symbol' is not assignable to type 'string'.// Type 'number' is not assignable to type 'string'.
🙁 Actual behavior
The T extends unknown version behaves differently from the unconstrained version.
🙂 Expected behavior
The two versions should have the same behavior, probably both being rejected since code like this is unsafe:
My theory is that this is for backwards compatibility when symbol keys were being added.
You can also get this behavior with any type whenever the apparent type of keyof T does NOT extend symbol | number.
For example:
constobjectConstraint=<Textends{abc: number}>(x: Example<T>): string=>x// OkconstnumberConstraint=<Textends123>(x: Example<T>): string=>x// Ok// ^ `keyof 123` happens to be only strings so also okay.
Notably this means that T extends {} actually errors. This furthers my hypothesis that the test is extends symbol | number ? error : do nothing because never technically extends symbol | number. To further this T extends {} | 1 doesn't error.
This does still leave unknown as a second special case though.
This is indeed a back-compat allowance; for a long time the default constraint was closer to {} than unknown (admittedly really neither). Hopefully we can eventually remove it but for now, unconstrained type parameters will sometimes appear to extend {}.
Activity
LukeAbby commentedon Feb 21, 2025
My theory is that this is for backwards compatibility when symbol keys were being added.
You can also get this behavior with any type whenever the apparent type of
keyof Tdoes NOT extendsymbol | number.For example:
Notably this means that
T extends {}actually errors. This furthers my hypothesis that the test isextends symbol | number ? error : do nothingbecausenevertechnically extendssymbol | number. To further thisT extends {} | 1doesn't error.This does still leave
unknownas a second special case though.mkantor commentedon Feb 21, 2025
#56652 seems possibly-relevant as well.
RyanCavanaugh commentedon Mar 24, 2025
This is indeed a back-compat allowance; for a long time the default constraint was closer to
{}thanunknown(admittedly really neither). Hopefully we can eventually remove it but for now, unconstrained type parameters will sometimes appear toextend {}.typescript-bot commentedon Mar 27, 2025
This issue has been marked as "Not a Defect" and has seen no recent activity. It has been automatically closed for house-keeping purposes.