@@ -298,12 +298,12 @@ namespace ts {
298
298
markerSubType.constraint = markerSuperType;
299
299
const markerOtherType = <TypeParameter>createType(TypeFlags.TypeParameter);
300
300
301
- const noTypePredicate: IdentifierTypePredicate = { kind: TypePredicateKind.Identifier, parameterName: "<<unresolved>>", parameterIndex: 0, type: anyType } ;
301
+ const noTypePredicate = createIdentifierTypePredicate( "<<unresolved>>", 0, anyType) ;
302
302
303
- const anySignature = createSignature(undefined, undefined, undefined, emptyArray, anyType, /*typePredicate*/ undefined , 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false);
304
- const unknownSignature = createSignature(undefined, undefined, undefined, emptyArray, unknownType, /*typePredicate*/ undefined , 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false);
305
- const resolvingSignature = createSignature(undefined, undefined, undefined, emptyArray, anyType, /*typePredicate*/ undefined , 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false);
306
- const silentNeverSignature = createSignature(undefined, undefined, undefined, emptyArray, silentNeverType, /*typePredicate*/ undefined , 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false);
303
+ const anySignature = createSignature(undefined, undefined, undefined, emptyArray, anyType, noTypePredicate , 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false);
304
+ const unknownSignature = createSignature(undefined, undefined, undefined, emptyArray, unknownType, noTypePredicate , 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false);
305
+ const resolvingSignature = createSignature(undefined, undefined, undefined, emptyArray, anyType, noTypePredicate , 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false);
306
+ const silentNeverSignature = createSignature(undefined, undefined, undefined, emptyArray, silentNeverType, noTypePredicate , 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false);
307
307
308
308
const enumNumberIndexInfo = createIndexInfo(stringType, /*isReadonly*/ true);
309
309
const jsObjectLiteralIndexInfo = createIndexInfo(anyType, /*isReadonly*/ false);
@@ -5490,8 +5490,17 @@ namespace ts {
5490
5490
resolveObjectTypeMembers(type, source, typeParameters, typeArguments);
5491
5491
}
5492
5492
5493
- function createSignature(declaration: SignatureDeclaration, typeParameters: TypeParameter[], thisParameter: Symbol | undefined, parameters: Symbol[],
5494
- resolvedReturnType: Type | undefined, resolvedTypePredicate: TypePredicate | undefined, minArgumentCount: number, hasRestParameter: boolean, hasLiteralTypes: boolean): Signature {
5493
+ function createSignature(
5494
+ declaration: SignatureDeclaration,
5495
+ typeParameters: TypeParameter[],
5496
+ thisParameter: Symbol | undefined,
5497
+ parameters: Symbol[],
5498
+ resolvedReturnType: Type | undefined,
5499
+ resolvedTypePredicate: TypePredicate | undefined,
5500
+ minArgumentCount: number,
5501
+ hasRestParameter: boolean,
5502
+ hasLiteralTypes: boolean,
5503
+ ): Signature {
5495
5504
const sig = new Signature(checker);
5496
5505
sig.declaration = declaration;
5497
5506
sig.typeParameters = typeParameters;
@@ -5506,8 +5515,8 @@ namespace ts {
5506
5515
}
5507
5516
5508
5517
function cloneSignature(sig: Signature): Signature {
5509
- return createSignature(sig.declaration, sig.typeParameters, sig.thisParameter, sig.parameters, sig. resolvedReturnType,
5510
- sig. resolvedTypePredicate, sig.minArgumentCount, sig.hasRestParameter, sig.hasLiteralTypes);
5518
+ return createSignature(sig.declaration, sig.typeParameters, sig.thisParameter, sig.parameters, /* resolvedReturnType*/ undefined ,
5519
+ /* resolvedTypePredicate*/ undefined , sig.minArgumentCount, sig.hasRestParameter, sig.hasLiteralTypes);
5511
5520
}
5512
5521
5513
5522
function getDefaultConstructSignatures(classType: InterfaceType): Signature[] {
@@ -5525,9 +5534,12 @@ namespace ts {
5525
5534
const minTypeArgumentCount = getMinTypeArgumentCount(baseSig.typeParameters);
5526
5535
const typeParamCount = length(baseSig.typeParameters);
5527
5536
if ((isJavaScript || typeArgCount >= minTypeArgumentCount) && typeArgCount <= typeParamCount) {
5528
- const sig = typeParamCount ? createSignatureInstantiation(baseSig, fillMissingTypeArguments(typeArguments, baseSig.typeParameters, minTypeArgumentCount, isJavaScript)) : cloneSignature(baseSig);
5537
+ const sig = typeParamCount
5538
+ ? createSignatureInstantiation(baseSig, fillMissingTypeArguments(typeArguments, baseSig.typeParameters, minTypeArgumentCount, isJavaScript))
5539
+ : cloneSignature(baseSig);
5529
5540
sig.typeParameters = classType.localTypeParameters;
5530
5541
sig.resolvedReturnType = classType;
5542
+ sig.resolvedTypePredicate = noTypePredicate;
5531
5543
result.push(sig);
5532
5544
}
5533
5545
}
@@ -5589,8 +5601,6 @@ namespace ts {
5589
5601
const thisType = getUnionType(map(unionSignatures, sig => getTypeOfSymbol(sig.thisParameter) || anyType), /*subtypeReduction*/ true);
5590
5602
s.thisParameter = createSymbolWithType(signature.thisParameter, thisType);
5591
5603
}
5592
- // Clear resolved return type we possibly got from cloneSignature
5593
- s.resolvedReturnType = undefined;
5594
5604
s.unionSignatures = unionSignatures;
5595
5605
}
5596
5606
(result || (result = [])).push(s);
@@ -5674,6 +5684,7 @@ namespace ts {
5674
5684
signatures = map(signatures, s => {
5675
5685
const clone = cloneSignature(s);
5676
5686
clone.resolvedReturnType = includeMixinType(getReturnTypeOfSignature(s), types, i);
5687
+ clone.resolvedTypePredicate = noTypePredicate; // TODO: GH#17757
5677
5688
return clone;
5678
5689
});
5679
5690
}
@@ -6103,14 +6114,13 @@ namespace ts {
6103
6114
6104
6115
function createUnionOrIntersectionProperty(containingType: UnionOrIntersectionType, name: __String): Symbol {
6105
6116
let props: Symbol[];
6106
- const types = containingType.types;
6107
6117
const isUnion = containingType.flags & TypeFlags.Union;
6108
6118
const excludeModifiers = isUnion ? ModifierFlags.NonPublicAccessibilityModifier : 0;
6109
6119
// Flags we want to propagate to the result if they exist in all source symbols
6110
6120
let commonFlags = isUnion ? SymbolFlags.None : SymbolFlags.Optional;
6111
6121
let syntheticFlag = CheckFlags.SyntheticMethod;
6112
6122
let checkFlags = 0;
6113
- for (const current of types) {
6123
+ for (const current of containingType. types) {
6114
6124
const type = getApparentType(current);
6115
6125
if (type !== unknownType) {
6116
6126
const prop = getPropertyOfType(type, name);
@@ -6344,22 +6354,26 @@ namespace ts {
6344
6354
6345
6355
function createTypePredicateFromTypePredicateNode(node: TypePredicateNode): IdentifierTypePredicate | ThisTypePredicate {
6346
6356
const { parameterName } = node;
6357
+ const type = getTypeFromTypeNode(node.type);
6347
6358
if (parameterName.kind === SyntaxKind.Identifier) {
6348
- return {
6349
- kind: TypePredicateKind.Identifier,
6350
- parameterName: parameterName ? parameterName.escapedText : undefined,
6351
- parameterIndex: parameterName ? getTypePredicateParameterIndex((node.parent as SignatureDeclaration).parameters, parameterName) : undefined,
6352
- type: getTypeFromTypeNode(node.type)
6353
- } as IdentifierTypePredicate;
6359
+ return createIdentifierTypePredicate(
6360
+ parameterName && parameterName.escapedText as string, // TODO: GH#18217
6361
+ parameterName && getTypePredicateParameterIndex((node.parent as SignatureDeclaration).parameters, parameterName),
6362
+ type);
6354
6363
}
6355
6364
else {
6356
- return {
6357
- kind: TypePredicateKind.This,
6358
- type: getTypeFromTypeNode(node.type)
6359
- };
6365
+ return createThisTypePredicate(type);
6360
6366
}
6361
6367
}
6362
6368
6369
+ function createIdentifierTypePredicate(parameterName: string | undefined, parameterIndex: number | undefined, type: Type): IdentifierTypePredicate {
6370
+ return { kind: TypePredicateKind.Identifier, parameterName, parameterIndex, type };
6371
+ }
6372
+
6373
+ function createThisTypePredicate(type: Type): ThisTypePredicate {
6374
+ return { kind: TypePredicateKind.This, type };
6375
+ }
6376
+
6363
6377
/**
6364
6378
* Gets the minimum number of type arguments needed to satisfy all non-optional type
6365
6379
* parameters.
@@ -6604,8 +6618,14 @@ namespace ts {
6604
6618
6605
6619
function getTypePredicateOfSignature(signature: Signature): TypePredicate | undefined {
6606
6620
if (!signature.resolvedTypePredicate) {
6607
- const targetTypePredicate = getTypePredicateOfSignature(signature.target);
6608
- signature.resolvedTypePredicate = targetTypePredicate ? instantiateTypePredicate(targetTypePredicate, signature.mapper) : noTypePredicate;
6621
+ if (signature.target) {
6622
+ const targetTypePredicate = getTypePredicateOfSignature(signature.target);
6623
+ signature.resolvedTypePredicate = targetTypePredicate ? instantiateTypePredicate(targetTypePredicate, signature.mapper) : noTypePredicate;
6624
+ }
6625
+ else {
6626
+ Debug.assert(!!signature.unionSignatures);
6627
+ signature.resolvedTypePredicate = getUnionTypePredicate(signature.unionSignatures);
6628
+ }
6609
6629
}
6610
6630
return signature.resolvedTypePredicate === noTypePredicate ? undefined : signature.resolvedTypePredicate;
6611
6631
}
@@ -7480,6 +7500,42 @@ namespace ts {
7480
7500
return getUnionTypeFromSortedList(typeSet, aliasSymbol, aliasTypeArguments);
7481
7501
}
7482
7502
7503
+ function getUnionTypePredicate(signatures: ReadonlyArray<Signature>): TypePredicate | undefined {
7504
+ let first: TypePredicate | undefined;
7505
+ const types: Type[] = [];
7506
+ for (let i = 0; i < signatures.length; i++) {
7507
+ const pred = getTypePredicateOfSignature(signatures[i]);
7508
+ if (!pred) {
7509
+ continue;
7510
+ }
7511
+
7512
+ if (first) {
7513
+ if (!typePredicateKindsMatch(first, pred)) {
7514
+ // No common type predicate.
7515
+ return undefined;
7516
+ }
7517
+ }
7518
+ else {
7519
+ first = pred;
7520
+ }
7521
+ types.push(pred.type);
7522
+ }
7523
+ if (!first) {
7524
+ // No union signatures had a type predicate.
7525
+ return undefined;
7526
+ }
7527
+ const unionType = getUnionType(types);
7528
+ return isIdentifierTypePredicate(first)
7529
+ ? createIdentifierTypePredicate(first.parameterName, first.parameterIndex, unionType)
7530
+ : createThisTypePredicate(unionType);
7531
+ }
7532
+
7533
+ function typePredicateKindsMatch(a: TypePredicate, b: TypePredicate): boolean {
7534
+ return isIdentifierTypePredicate(a)
7535
+ ? isIdentifierTypePredicate(b) && a.parameterIndex === b.parameterIndex
7536
+ : !isIdentifierTypePredicate(b);
7537
+ }
7538
+
7483
7539
// This function assumes the constituent type list is sorted and deduplicated.
7484
7540
function getUnionTypeFromSortedList(types: Type[], aliasSymbol?: Symbol, aliasTypeArguments?: Type[]): Type {
7485
7541
if (types.length === 0) {
@@ -10167,11 +10223,20 @@ namespace ts {
10167
10223
result &= related;
10168
10224
}
10169
10225
if (!ignoreReturnTypes) {
10170
- result &= compareTypes(getReturnTypeOfSignature(source), getReturnTypeOfSignature(target));
10226
+ const sourceTypePredicate = getTypePredicateOfSignature(source);
10227
+ const targetTypePredicate = getTypePredicateOfSignature(target);
10228
+ result &= sourceTypePredicate !== undefined || targetTypePredicate !== undefined
10229
+ ? compareTypePredicatesIdentical(sourceTypePredicate, targetTypePredicate, compareTypes)
10230
+ // If they're both type predicates their return types will both be `boolean`, so no need to compare those.
10231
+ : compareTypes(getReturnTypeOfSignature(source), getReturnTypeOfSignature(target));
10171
10232
}
10172
10233
return result;
10173
10234
}
10174
10235
10236
+ function compareTypePredicatesIdentical(source: TypePredicate | undefined, target: TypePredicate | undefined, compareTypes: (s: Type, t: Type) => Ternary): Ternary {
10237
+ return source === undefined || target === undefined || !typePredicateKindsMatch(source, target) ? Ternary.False : compareTypes(source.type, target.type);
10238
+ }
10239
+
10175
10240
function isRestParameterIndex(signature: Signature, parameterIndex: number) {
10176
10241
return signature.hasRestParameter && parameterIndex >= signature.parameters.length - 1;
10177
10242
}
@@ -13612,8 +13677,6 @@ namespace ts {
13612
13677
let result: Signature;
13613
13678
if (signatureList) {
13614
13679
result = cloneSignature(signatureList[0]);
13615
- // Clear resolved return type we possibly got from cloneSignature
13616
- result.resolvedReturnType = undefined;
13617
13680
result.unionSignatures = signatureList;
13618
13681
}
13619
13682
return result;
0 commit comments