@@ -32166,18 +32166,25 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
32166
32166
32167
32167
// If type has a single call signature and no other members, return that signature. Otherwise, return undefined.
32168
32168
function getSingleCallSignature(type: Type): Signature | undefined {
32169
- return getSingleSignature(type, SignatureKind.Call, /*allowMembers */ false);
32169
+ return getSingleSignature(type, SignatureKind.Call, /*allowMembersWithTypeVariables */ false);
32170
32170
}
32171
32171
32172
32172
function getSingleCallOrConstructSignature(type: Type): Signature | undefined {
32173
- return getSingleSignature(type, SignatureKind.Call, /*allowMembers */ false) ||
32174
- getSingleSignature(type, SignatureKind.Construct, /*allowMembers */ false);
32173
+ return getSingleSignature(type, SignatureKind.Call, /*allowMembersWithTypeVariables */ false) ||
32174
+ getSingleSignature(type, SignatureKind.Construct, /*allowMembersWithTypeVariables */ false);
32175
32175
}
32176
32176
32177
- function getSingleSignature(type: Type, kind: SignatureKind, allowMembers: boolean): Signature | undefined {
32177
+ function couldMembersContainTypeVariables(resolved: ResolvedType) {
32178
+ return some(resolved.properties, sym => couldContainTypeVariables(getTypeOfSymbol(sym))) ||
32179
+ some(resolved.indexInfos, info => couldContainTypeVariables(info.type));
32180
+ }
32181
+
32182
+ function getSingleSignature(type: Type, kind: SignatureKind, allowMembersWithTypeVariables: boolean): Signature | undefined {
32178
32183
if (type.flags & TypeFlags.Object) {
32179
32184
const resolved = resolveStructuredTypeMembers(type as ObjectType);
32180
- if (allowMembers || resolved.properties.length === 0 && resolved.indexInfos.length === 0) {
32185
+ // We could validate that the other members don't reference the type parameters we want to promote to the signature.
32186
+ // That's pretty hard, so a reasonable proxy is checking that the other members of the type don't reference any type variables at all.
32187
+ if (allowMembersWithTypeVariables || !couldMembersContainTypeVariables(resolved)) {
32181
32188
if (kind === SignatureKind.Call && resolved.callSignatures.length === 1 && resolved.constructSignatures.length === 0) {
32182
32189
return resolved.callSignatures[0];
32183
32190
}
@@ -37346,13 +37353,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
37346
37353
37347
37354
function instantiateTypeWithSingleGenericCallSignature(node: Expression | MethodDeclaration | QualifiedName, type: Type, checkMode?: CheckMode) {
37348
37355
if (checkMode && checkMode & (CheckMode.Inferential | CheckMode.SkipGenericFunctions)) {
37349
- const callSignature = getSingleSignature(type, SignatureKind.Call, /*allowMembers */ true);
37350
- const constructSignature = getSingleSignature(type, SignatureKind.Construct, /*allowMembers */ true);
37356
+ const callSignature = getSingleSignature(type, SignatureKind.Call, /*allowMembersWithTypeVariables */ true);
37357
+ const constructSignature = getSingleSignature(type, SignatureKind.Construct, /*allowMembersWithTypeVariables */ true);
37351
37358
const signature = callSignature || constructSignature;
37352
37359
if (signature && signature.typeParameters) {
37353
37360
const contextualType = getApparentTypeOfContextualType(node as Expression, ContextFlags.NoConstraints);
37354
37361
if (contextualType) {
37355
- const contextualSignature = getSingleSignature(getNonNullableType(contextualType), callSignature ? SignatureKind.Call : SignatureKind.Construct, /*allowMembers */ true );
37362
+ const contextualSignature = getSingleSignature(getNonNullableType(contextualType), callSignature ? SignatureKind.Call : SignatureKind.Construct, /*allowMembersWithTypeVariables */ false );
37356
37363
if (contextualSignature && !contextualSignature.typeParameters) {
37357
37364
if (checkMode & CheckMode.SkipGenericFunctions) {
37358
37365
skippedGenericFunction(node, checkMode);
0 commit comments