diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 58d6a8b867e20..9084995db80cf 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -15276,7 +15276,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return undefined; } - function getSignatureInstantiation(signature: Signature, typeArguments: Type[] | undefined, isJavascript: boolean, inferredTypeParameters?: readonly TypeParameter[]): Signature { + function getSignatureInstantiation(signature: Signature, typeArguments: readonly Type[] | undefined, isJavascript: boolean, inferredTypeParameters?: readonly TypeParameter[]): Signature { const instantiatedSignature = getSignatureInstantiationWithoutFillingInTypeArguments(signature, fillMissingTypeArguments(typeArguments, signature.typeParameters, getMinTypeArgumentCount(signature.typeParameters), isJavascript)); if (inferredTypeParameters) { const returnSignature = getSingleCallOrConstructSignature(getReturnTypeOfSignature(instantiatedSignature)); @@ -22963,10 +22963,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { ) { // 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. + // of the much more expensive N * M comparison matrix we explore below. We instantiate the source + // signature with the type parameters of the target signature to unify the two. for (let i = 0; i < targetSignatures.length; i++) { - const related = signatureRelatedTo(sourceSignatures[i], targetSignatures[i], /*erase*/ true, reportErrors, intersectionState, incompatibleReporter(sourceSignatures[i], targetSignatures[i])); + const sourceSignature = sourceSignatures[i]; + const targetSignature = targetSignatures[i]; + const instantiatedSourceSignature = targetSignature.typeParameters ? + getSignatureInstantiation(sourceSignature, targetSignature.typeParameters, isInJSFile(sourceSignature.declaration)) : + sourceSignature; + const related = signatureRelatedTo(instantiatedSourceSignature, targetSignature, /*erase*/ false, reportErrors, intersectionState, incompatibleReporter(instantiatedSourceSignature, targetSignature)); if (!related) { return Ternary.False; } diff --git a/tests/baselines/reference/complexRecursiveCollections.types b/tests/baselines/reference/complexRecursiveCollections.types index 0aa394d46b370..2a6a5c12d81a7 100644 --- a/tests/baselines/reference/complexRecursiveCollections.types +++ b/tests/baselines/reference/complexRecursiveCollections.types @@ -1139,7 +1139,7 @@ declare module Immutable { >Seq : typeof Seq function isSeq(maybeSeq: any): maybeSeq is Seq.Indexed | Seq.Keyed; ->isSeq : (maybeSeq: any) => maybeSeq is Indexed | Keyed +>isSeq : (maybeSeq: any) => maybeSeq is Keyed | Indexed >maybeSeq : any >Seq : any >Seq : any diff --git a/tests/baselines/reference/genericSignatureRelations.js b/tests/baselines/reference/genericSignatureRelations.js new file mode 100644 index 0000000000000..48b363df00765 --- /dev/null +++ b/tests/baselines/reference/genericSignatureRelations.js @@ -0,0 +1,25 @@ +//// [tests/cases/compiler/genericSignatureRelations.ts] //// + +//// [genericSignatureRelations.ts] +// Repro from #48070 + +type S = () => T extends X ? 1 : '2'; + +type Foo1 = S<'s1'>; +type Foo2 = S<'s2'>; + +type Result1 = Foo1 extends Foo2 ? true : false; +type Result2 = S<'s1'> extends S<'s2'> ? true : false; + + +//// [genericSignatureRelations.js] +"use strict"; +// Repro from #48070 + + +//// [genericSignatureRelations.d.ts] +type S = () => T extends X ? 1 : '2'; +type Foo1 = S<'s1'>; +type Foo2 = S<'s2'>; +type Result1 = Foo1 extends Foo2 ? true : false; +type Result2 = S<'s1'> extends S<'s2'> ? true : false; diff --git a/tests/baselines/reference/genericSignatureRelations.symbols b/tests/baselines/reference/genericSignatureRelations.symbols new file mode 100644 index 0000000000000..13a4c1233afbc --- /dev/null +++ b/tests/baselines/reference/genericSignatureRelations.symbols @@ -0,0 +1,30 @@ +//// [tests/cases/compiler/genericSignatureRelations.ts] //// + +=== genericSignatureRelations.ts === +// Repro from #48070 + +type S = () => T extends X ? 1 : '2'; +>S : Symbol(S, Decl(genericSignatureRelations.ts, 0, 0)) +>X : Symbol(X, Decl(genericSignatureRelations.ts, 2, 7)) +>T : Symbol(T, Decl(genericSignatureRelations.ts, 2, 13)) +>T : Symbol(T, Decl(genericSignatureRelations.ts, 2, 13)) +>X : Symbol(X, Decl(genericSignatureRelations.ts, 2, 7)) + +type Foo1 = S<'s1'>; +>Foo1 : Symbol(Foo1, Decl(genericSignatureRelations.ts, 2, 43)) +>S : Symbol(S, Decl(genericSignatureRelations.ts, 0, 0)) + +type Foo2 = S<'s2'>; +>Foo2 : Symbol(Foo2, Decl(genericSignatureRelations.ts, 4, 20)) +>S : Symbol(S, Decl(genericSignatureRelations.ts, 0, 0)) + +type Result1 = Foo1 extends Foo2 ? true : false; +>Result1 : Symbol(Result1, Decl(genericSignatureRelations.ts, 5, 20)) +>Foo1 : Symbol(Foo1, Decl(genericSignatureRelations.ts, 2, 43)) +>Foo2 : Symbol(Foo2, Decl(genericSignatureRelations.ts, 4, 20)) + +type Result2 = S<'s1'> extends S<'s2'> ? true : false; +>Result2 : Symbol(Result2, Decl(genericSignatureRelations.ts, 7, 48)) +>S : Symbol(S, Decl(genericSignatureRelations.ts, 0, 0)) +>S : Symbol(S, Decl(genericSignatureRelations.ts, 0, 0)) + diff --git a/tests/baselines/reference/genericSignatureRelations.types b/tests/baselines/reference/genericSignatureRelations.types new file mode 100644 index 0000000000000..b923d1a246610 --- /dev/null +++ b/tests/baselines/reference/genericSignatureRelations.types @@ -0,0 +1,24 @@ +//// [tests/cases/compiler/genericSignatureRelations.ts] //// + +=== genericSignatureRelations.ts === +// Repro from #48070 + +type S = () => T extends X ? 1 : '2'; +>S : S + +type Foo1 = S<'s1'>; +>Foo1 : () => T extends "s1" ? 1 : "2" + +type Foo2 = S<'s2'>; +>Foo2 : () => T extends "s2" ? 1 : "2" + +type Result1 = Foo1 extends Foo2 ? true : false; +>Result1 : false +>true : true +>false : false + +type Result2 = S<'s1'> extends S<'s2'> ? true : false; +>Result2 : false +>true : true +>false : false + diff --git a/tests/cases/compiler/genericSignatureRelations.ts b/tests/cases/compiler/genericSignatureRelations.ts new file mode 100644 index 0000000000000..c2e6ef3daaa6f --- /dev/null +++ b/tests/cases/compiler/genericSignatureRelations.ts @@ -0,0 +1,12 @@ +// @strict: true +// @declaration: true + +// Repro from #48070 + +type S = () => T extends X ? 1 : '2'; + +type Foo1 = S<'s1'>; +type Foo2 = S<'s2'>; + +type Result1 = Foo1 extends Foo2 ? true : false; +type Result2 = S<'s1'> extends S<'s2'> ? true : false;