-
Notifications
You must be signed in to change notification settings - Fork 12.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Generic type alias produces erroneously compatible types #31006
Comments
Behavior dates back to TS 2.1 when the syntax was first legal. |
And it's not like we don't know type Params<T> = T extends (arg: infer A, arg2: infer B) => any ? [A, B] : never;
type DA = Params<Demo<A>>; // ['a', number]
type DB = Params<Demo<B>>; // ['b', string]
declare let da: DA, db: DB;
da = db; // Error 🤷♀️ |
The key issue here is that we erase function type parameters (i.e. replace them with if (getObjectFlags(source) & ObjectFlags.Instantiated && getObjectFlags(target) & ObjectFlags.Instantiated && source.symbol === target.symbol) {
// We have instantiations of the same anonymous type (which typically will be the type of a
// method). Simply do a pairwise comparison of the signatures in the two signature lists instead
// of the much more expensive N * M comparison matrix we explore below. We erase type parameters
// as they are known to always be the same.
for (let i = 0; i < targetSignatures.length; i++) {
const related = signatureRelatedTo(sourceSignatures[i], targetSignatures[i], /*erase*/ true, reportErrors);
if (!related) {
return Ternary.False;
}
result &= related;
}
} This obviously looses some information, but that's generally fine as long as the type parameters have no constraints, non-generic constraints, or constraints that reference other type parameters in the same type parameter list, because they're then known to be identical in the two signatures we're relating. However, when type parameters have constraints that reference outer type parameters (as is the case in the I think the solution is to apply |
I think we should proooobably also move the |
@weswigham No, the current ordering is good. We definitely want to first recognize instantiations of the same signature because that tells us that function type parameters (if any) are identical, allowing us to erase them to their constraints. |
The Definitely Typed valiation suites turned up several packages that are affected by this (errors and performance regressions). We need some more time to analyze and decide whether the cure is worse than the disease. |
it looks like this was fixed years ago lol |
Indeed! |
TypeScript Version: 3.5.0-dev.20190417
Search Terms:
generics, resolved, nested generics, specified, assignable, type safety, type alias, compatible
Code
Expected behavior:
There should be an error that a type
Demo<A>
is not assignable toDemo<B>
.Actual behavior:
It compiles with no error.
I guess the compiler "forgets" what concrete type
T
is, since it doesn't appear directly in the resulting type. If one manually substitutesA
andB
forT
into the definition ofDemo<T>
to makeDemoA
andDemoB
, everything behaves as expected:This comes from a question on Stack Overflow.
Playground Link:
👩💻🔗
Related Issues:
I'm not finding anything I am confident is related: 🔍👀∅⁉
The text was updated successfully, but these errors were encountered: