From a9c15efeb7edea222f565e9bbc3de04e666148b8 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Mon, 8 Feb 2021 17:52:51 -0800 Subject: [PATCH] Base signatures resolve only the type parameters local to the signature, not all type parameters --- src/compiler/checker.ts | 15 +++++++++++++-- src/compiler/types.ts | 2 ++ ...peGenericInSignatureTypeParameterConstraint.js | 7 +++++++ ...ericInSignatureTypeParameterConstraint.symbols | 15 +++++++++++++++ ...enericInSignatureTypeParameterConstraint.types | 8 ++++++++ ...peGenericInSignatureTypeParameterConstraint.ts | 4 ++++ 6 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 tests/baselines/reference/conditionalTypeGenericInSignatureTypeParameterConstraint.js create mode 100644 tests/baselines/reference/conditionalTypeGenericInSignatureTypeParameterConstraint.symbols create mode 100644 tests/baselines/reference/conditionalTypeGenericInSignatureTypeParameterConstraint.types create mode 100644 tests/cases/compiler/conditionalTypeGenericInSignatureTypeParameterConstraint.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index bf7d17a951f72..1997dc946be64 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -12199,9 +12199,20 @@ namespace ts { function getBaseSignature(signature: Signature) { const typeParameters = signature.typeParameters; if (typeParameters) { + if (signature.baseSignatureCache) { + return signature.baseSignatureCache; + } const typeEraser = createTypeEraser(typeParameters); - const baseConstraints = map(typeParameters, tp => instantiateType(getBaseConstraintOfType(tp), typeEraser) || unknownType); - return instantiateSignature(signature, createTypeMapper(typeParameters, baseConstraints), /*eraseTypeParameters*/ true); + const baseConstraintMapper = createTypeMapper(typeParameters, map(typeParameters, tp => getConstraintOfTypeParameter(tp) || unknownType)); + let baseConstraints: readonly Type[] = map(typeParameters, tp => instantiateType(tp, baseConstraintMapper) || unknownType); + // Run N type params thru the immediate constraint mapper up to N times + // This way any noncircular interdependent type parameters are definitely resolved to their external dependencies + for (let i = 0; i < typeParameters.length - 1; i++) { + baseConstraints = instantiateTypes(baseConstraints, baseConstraintMapper); + } + // and then apply a type eraser to remove any remaining circularly dependent type parameters + baseConstraints = instantiateTypes(baseConstraints, typeEraser); + return signature.baseSignatureCache = instantiateSignature(signature, createTypeMapper(typeParameters, baseConstraints), /*eraseTypeParameters*/ true); } return signature; } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 3585ff50a8f3b..ad8f560a0d7a8 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -5552,6 +5552,8 @@ namespace ts { /* @internal */ canonicalSignatureCache?: Signature; // Canonical version of signature (deferred) /* @internal */ + baseSignatureCache?: Signature; // Base version of signature (deferred) + /* @internal */ optionalCallSignatureCache?: { inner?: Signature, outer?: Signature }; // Optional chained call version of signature (deferred) /* @internal */ isolatedSignatureType?: ObjectType; // A manufactured type that just contains the signature for purposes of signature comparison diff --git a/tests/baselines/reference/conditionalTypeGenericInSignatureTypeParameterConstraint.js b/tests/baselines/reference/conditionalTypeGenericInSignatureTypeParameterConstraint.js new file mode 100644 index 0000000000000..0e8bb8e7f372e --- /dev/null +++ b/tests/baselines/reference/conditionalTypeGenericInSignatureTypeParameterConstraint.js @@ -0,0 +1,7 @@ +//// [conditionalTypeGenericInSignatureTypeParameterConstraint.ts] +// should be x +type H_inline1 = (() => o) extends (() => infer o) ? o : never; + +type Result = H_inline1; // should be `string` + +//// [conditionalTypeGenericInSignatureTypeParameterConstraint.js] diff --git a/tests/baselines/reference/conditionalTypeGenericInSignatureTypeParameterConstraint.symbols b/tests/baselines/reference/conditionalTypeGenericInSignatureTypeParameterConstraint.symbols new file mode 100644 index 0000000000000..9d53c7de537e5 --- /dev/null +++ b/tests/baselines/reference/conditionalTypeGenericInSignatureTypeParameterConstraint.symbols @@ -0,0 +1,15 @@ +=== tests/cases/compiler/conditionalTypeGenericInSignatureTypeParameterConstraint.ts === +// should be x +type H_inline1 = (() => o) extends (() => infer o) ? o : never; +>H_inline1 : Symbol(H_inline1, Decl(conditionalTypeGenericInSignatureTypeParameterConstraint.ts, 0, 0)) +>x : Symbol(x, Decl(conditionalTypeGenericInSignatureTypeParameterConstraint.ts, 1, 15)) +>o : Symbol(o, Decl(conditionalTypeGenericInSignatureTypeParameterConstraint.ts, 1, 22)) +>x : Symbol(x, Decl(conditionalTypeGenericInSignatureTypeParameterConstraint.ts, 1, 15)) +>o : Symbol(o, Decl(conditionalTypeGenericInSignatureTypeParameterConstraint.ts, 1, 22)) +>o : Symbol(o, Decl(conditionalTypeGenericInSignatureTypeParameterConstraint.ts, 1, 63)) +>o : Symbol(o, Decl(conditionalTypeGenericInSignatureTypeParameterConstraint.ts, 1, 63)) + +type Result = H_inline1; // should be `string` +>Result : Symbol(Result, Decl(conditionalTypeGenericInSignatureTypeParameterConstraint.ts, 1, 79)) +>H_inline1 : Symbol(H_inline1, Decl(conditionalTypeGenericInSignatureTypeParameterConstraint.ts, 0, 0)) + diff --git a/tests/baselines/reference/conditionalTypeGenericInSignatureTypeParameterConstraint.types b/tests/baselines/reference/conditionalTypeGenericInSignatureTypeParameterConstraint.types new file mode 100644 index 0000000000000..6da7d02ad9afd --- /dev/null +++ b/tests/baselines/reference/conditionalTypeGenericInSignatureTypeParameterConstraint.types @@ -0,0 +1,8 @@ +=== tests/cases/compiler/conditionalTypeGenericInSignatureTypeParameterConstraint.ts === +// should be x +type H_inline1 = (() => o) extends (() => infer o) ? o : never; +>H_inline1 : x + +type Result = H_inline1; // should be `string` +>Result : string + diff --git a/tests/cases/compiler/conditionalTypeGenericInSignatureTypeParameterConstraint.ts b/tests/cases/compiler/conditionalTypeGenericInSignatureTypeParameterConstraint.ts new file mode 100644 index 0000000000000..b4f8c3507f5aa --- /dev/null +++ b/tests/cases/compiler/conditionalTypeGenericInSignatureTypeParameterConstraint.ts @@ -0,0 +1,4 @@ +// should be x +type H_inline1 = (() => o) extends (() => infer o) ? o : never; + +type Result = H_inline1; // should be `string` \ No newline at end of file