@@ -2990,7 +2990,7 @@ namespace ts {
2990
2990
(<GenericType>type).typeArguments = type.typeParameters;
2991
2991
type.thisType = <TypeParameter>createType(TypeFlags.TypeParameter | TypeFlags.ThisType);
2992
2992
type.thisType.symbol = symbol;
2993
- type.thisType.constraint = getTypeWithThisArgument( type) ;
2993
+ type.thisType.constraint = type;
2994
2994
}
2995
2995
}
2996
2996
return <InterfaceType>links.declaredType;
@@ -3533,19 +3533,29 @@ namespace ts {
3533
3533
return type.flags & TypeFlags.UnionOrIntersection ? getPropertiesOfUnionOrIntersectionType(<UnionType>type) : getPropertiesOfObjectType(type);
3534
3534
}
3535
3535
3536
+ /**
3537
+ * The apparent type of a type parameter is the base constraint instantiated with the type parameter
3538
+ * as the type argument for the 'this' type.
3539
+ */
3540
+ function getApparentTypeOfTypeParameter(type: TypeParameter) {
3541
+ if (!type.resolvedApparentType) {
3542
+ let constraintType = getConstraintOfTypeParameter(type);
3543
+ while (constraintType && constraintType.flags & TypeFlags.TypeParameter) {
3544
+ constraintType = getConstraintOfTypeParameter(<TypeParameter>constraintType);
3545
+ }
3546
+ type.resolvedApparentType = getTypeWithThisArgument(constraintType || emptyObjectType, type);
3547
+ }
3548
+ return type.resolvedApparentType;
3549
+ }
3550
+
3536
3551
/**
3537
3552
* For a type parameter, return the base constraint of the type parameter. For the string, number,
3538
3553
* boolean, and symbol primitive types, return the corresponding object types. Otherwise return the
3539
3554
* type itself. Note that the apparent type of a union type is the union type itself.
3540
3555
*/
3541
3556
function getApparentType(type: Type): Type {
3542
3557
if (type.flags & TypeFlags.TypeParameter) {
3543
- do {
3544
- type = getConstraintOfTypeParameter(<TypeParameter>type);
3545
- } while (type && type.flags & TypeFlags.TypeParameter);
3546
- if (!type) {
3547
- type = emptyObjectType;
3548
- }
3558
+ type = getApparentTypeOfTypeParameter(<TypeParameter>type);
3549
3559
}
3550
3560
if (type.flags & TypeFlags.StringLike) {
3551
3561
type = globalStringType;
@@ -5603,18 +5613,31 @@ namespace ts {
5603
5613
return compareTypes(getTypeOfSymbol(sourceProp), getTypeOfSymbol(targetProp));
5604
5614
}
5605
5615
5616
+ function isMatchingSignature(source: Signature, target: Signature, partialMatch: boolean) {
5617
+ // A source signature matches a target signature if the two signatures have the same number of required,
5618
+ // optional, and rest parameters.
5619
+ if (source.parameters.length === target.parameters.length &&
5620
+ source.minArgumentCount === target.minArgumentCount &&
5621
+ source.hasRestParameter === target.hasRestParameter) {
5622
+ return true;
5623
+ }
5624
+ // A source signature partially matches a target signature if the target signature has no fewer required
5625
+ // parameters and no more overall parameters than the source signature (where a signature with a rest
5626
+ // parameter is always considered to have more overall parameters than one without).
5627
+ if (partialMatch && source.minArgumentCount <= target.minArgumentCount && (
5628
+ source.hasRestParameter && !target.hasRestParameter ||
5629
+ source.hasRestParameter === target.hasRestParameter && source.parameters.length >= target.parameters.length)) {
5630
+ return true;
5631
+ }
5632
+ return false;
5633
+ }
5634
+
5606
5635
function compareSignatures(source: Signature, target: Signature, partialMatch: boolean, ignoreReturnTypes: boolean, compareTypes: (s: Type, t: Type) => Ternary): Ternary {
5607
5636
if (source === target) {
5608
5637
return Ternary.True;
5609
5638
}
5610
- if (source.parameters.length !== target.parameters.length ||
5611
- source.minArgumentCount !== target.minArgumentCount ||
5612
- source.hasRestParameter !== target.hasRestParameter) {
5613
- if (!partialMatch ||
5614
- source.parameters.length < target.parameters.length && !source.hasRestParameter ||
5615
- source.minArgumentCount > target.minArgumentCount) {
5616
- return Ternary.False;
5617
- }
5639
+ if (!(isMatchingSignature(source, target, partialMatch))) {
5640
+ return Ternary.False;
5618
5641
}
5619
5642
let result = Ternary.True;
5620
5643
if (source.typeParameters && target.typeParameters) {
@@ -6421,9 +6444,10 @@ namespace ts {
6421
6444
6422
6445
function narrowTypeByInstanceof(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type {
6423
6446
// Check that type is not any, assumed result is true, and we have variable symbol on the left
6424
- if (isTypeAny(type) || !assumeTrue || expr.left.kind !== SyntaxKind.Identifier || getResolvedSymbol(<Identifier>expr.left) !== symbol) {
6447
+ if (isTypeAny(type) || expr.left.kind !== SyntaxKind.Identifier || getResolvedSymbol(<Identifier>expr.left) !== symbol) {
6425
6448
return type;
6426
6449
}
6450
+
6427
6451
// Check that right operand is a function type with a prototype property
6428
6452
const rightType = checkExpression(expr.right);
6429
6453
if (!isTypeSubtypeOf(rightType, globalFunctionType)) {
@@ -6455,6 +6479,13 @@ namespace ts {
6455
6479
}
6456
6480
6457
6481
if (targetType) {
6482
+ if (!assumeTrue) {
6483
+ if (type.flags & TypeFlags.Union) {
6484
+ return getUnionType(filter((<UnionType>type).types, t => !isTypeSubtypeOf(t, targetType)));
6485
+ }
6486
+ return type;
6487
+ }
6488
+
6458
6489
return getNarrowedType(type, targetType);
6459
6490
}
6460
6491
0 commit comments