From 5df9c3a709ccaf84dacbad59bf6ec26bc3acdad6 Mon Sep 17 00:00:00 2001 From: Nathan Fenner Date: Fri, 11 Jan 2019 15:53:34 -0800 Subject: [PATCH 1/5] Infer generic type arguments when narrowing to generic class with instanceof --- src/compiler/checker.ts | 76 +++ .../narrowGenericTypeByInstanceOf.errors.txt | 324 ++++++++++ .../narrowGenericTypeByInstanceOf.js | 444 ++++++++++++++ .../narrowGenericTypeByInstanceOf.symbols | 580 ++++++++++++++++++ .../narrowGenericTypeByInstanceOf.types | 540 ++++++++++++++++ .../compiler/narrowGenericTypeByInstanceOf.ts | 218 +++++++ 6 files changed, 2182 insertions(+) create mode 100644 tests/baselines/reference/narrowGenericTypeByInstanceOf.errors.txt create mode 100644 tests/baselines/reference/narrowGenericTypeByInstanceOf.js create mode 100644 tests/baselines/reference/narrowGenericTypeByInstanceOf.symbols create mode 100644 tests/baselines/reference/narrowGenericTypeByInstanceOf.types create mode 100644 tests/cases/compiler/narrowGenericTypeByInstanceOf.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 86822e2487846..f9cb78d14b545 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -16061,6 +16061,76 @@ namespace ts { return getTypeWithFacts(mapType(type, narrowTypeForTypeofSwitch(impliedType)), switchFacts); } + function inferSubtypeTypeParameters(superType: Type, childTypeParameters: ReadonlyArray, childConstructor: Signature): Type | undefined { + // inferSubtypeTypeParameters infers the best possible parameters for the given childConstructor such that it represents every possible subtype of superType. + // An inferenceContext is created to permit us to develop inferences. + const inferenceContext = createInferenceContext( + childTypeParameters, + childConstructor, + InferenceFlags.AnyDefault, // TODO: we might consider stricter flags in the future + ); + + // Infer the types from superType onto the return type of the child constructor. + inferTypes(inferenceContext.inferences, superType, getReturnTypeOfSignature(childConstructor), InferencePriority.ReturnType); + + // We extract the inferred arguments from the inference context. + const childArguments = getInferredTypes(inferenceContext); + + // Lastly, supply the childType with the new parameters. + return instantiateType(getReturnTypeOfSignature(childConstructor), param => { + if (childTypeParameters.indexOf(param) >= 0) { + return childArguments[childTypeParameters.indexOf(param)]; + } + return param; + }); + } + + function narrowTypeParametersByAssignability(superType: Type, childType: Type): Type | undefined { + if (superType.flags & TypeFlags.Never) { + return undefined; + } + // Attempt to narrow `superType` to `childType`. + // If this is possible via an instantiation of childType's parameters, return the narrowed type. + // Otherwise, return undefined. + + if (!(childType.flags & TypeFlags.Object)) { + return undefined; + } + + const childObjectType = childType; + + if (!childObjectType.constructSignatures) { + // TODO: can we do anything if a construct signature doesn't exist? + return undefined; + } + + if (childObjectType.constructSignatures.length === 0) { + // TODO: can we do anything if a construct signature doesn't exist? + return undefined; + } + + // TODO: how should we select the constructor if there is more than one? + // We should probably select the most-general overload, or maybe try all of them. + const childConstructor = childObjectType.constructSignatures[0]; + + if (!childConstructor.typeParameters) { + // Narrowing via type parameter assignment is only feasible if type parameters exist. + return undefined; + } + + const childTypeParameters = childConstructor.typeParameters; + + if (superType.flags & TypeFlags.Union) { + // When the super type is a union type, it makes sense to spread across. + // If it's possible for the child type to be a subtype, then we should instead skip it. + return getUnionType( + (superType).types.map(superTypeAlternative => inferSubtypeTypeParameters(superTypeAlternative, childTypeParameters, childConstructor)).map(type => type || neverType) + ); + } + + return inferSubtypeTypeParameters(superType, childTypeParameters, childConstructor); + } + function narrowTypeByInstanceof(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type { const left = getReferenceCandidate(expr.left); if (!isMatchingReference(reference, left)) { @@ -16086,6 +16156,12 @@ namespace ts { if (!isTypeAny(prototypePropertyType)) { targetType = prototypePropertyType; } + + const narrowedGenericClassTypeCandidate = narrowTypeParametersByAssignability(type, rightType); + if (narrowedGenericClassTypeCandidate && !(narrowedGenericClassTypeCandidate.flags & TypeFlags.Never)) { + // When applicable, this overrides the basic target. + targetType = narrowedGenericClassTypeCandidate; + } } // Don't narrow from 'any' if the target type is exactly 'Object' or 'Function' diff --git a/tests/baselines/reference/narrowGenericTypeByInstanceOf.errors.txt b/tests/baselines/reference/narrowGenericTypeByInstanceOf.errors.txt new file mode 100644 index 0000000000000..3b98c6edc9354 --- /dev/null +++ b/tests/baselines/reference/narrowGenericTypeByInstanceOf.errors.txt @@ -0,0 +1,324 @@ +tests/cases/compiler/narrowGenericTypeByInstanceOf.ts(1,27): error TS2307: Cannot find module 'querystring'. +tests/cases/compiler/narrowGenericTypeByInstanceOf.ts(24,21): error TS2345: Argument of type 'Child' is not assignable to parameter of type 'Child'. + Type 'number' is not assignable to type 'string'. +tests/cases/compiler/narrowGenericTypeByInstanceOf.ts(49,21): error TS2345: Argument of type 'Child' is not assignable to parameter of type 'Child'. + Type 'number' is not assignable to type 'string'. +tests/cases/compiler/narrowGenericTypeByInstanceOf.ts(77,27): error TS2345: Argument of type 'Child' is not assignable to parameter of type 'Child'. + Type 'string' is not assignable to type 'number'. +tests/cases/compiler/narrowGenericTypeByInstanceOf.ts(108,21): error TS2345: Argument of type 'Parent & Child' is not assignable to parameter of type 'Child'. + Types of property 'value3' are incompatible. + Type 'string | number' is not assignable to type 'number'. + Type 'string' is not assignable to type 'number'. +tests/cases/compiler/narrowGenericTypeByInstanceOf.ts(109,21): error TS2345: Argument of type 'Parent & Child' is not assignable to parameter of type 'Child'. + Types of property 'value3' are incompatible. + Type 'string | number' is not assignable to type 'string'. + Type 'number' is not assignable to type 'string'. +tests/cases/compiler/narrowGenericTypeByInstanceOf.ts(110,30): error TS2345: Argument of type 'Parent & Child' is not assignable to parameter of type 'Child'. + Types of property 'value3' are incompatible. + Type 'string | number' is not assignable to type 'string & number'. + Type 'string' is not assignable to type 'string & number'. + Type 'string' is not assignable to type 'number'. +tests/cases/compiler/narrowGenericTypeByInstanceOf.ts(114,21): error TS2345: Argument of type 'Child' is not assignable to parameter of type 'Child'. + Type 'number' is not assignable to type 'string'. +tests/cases/compiler/narrowGenericTypeByInstanceOf.ts(115,30): error TS2345: Argument of type 'Child' is not assignable to parameter of type 'Child'. + Type 'number' is not assignable to type 'string & number'. + Type 'number' is not assignable to type 'string'. +tests/cases/compiler/narrowGenericTypeByInstanceOf.ts(142,16): error TS2345: Argument of type 'Parent & Child' is not assignable to parameter of type 'Child'. + Types of property 'value3' are incompatible. + Type 'S | T' is not assignable to type 'S'. + Type 'T' is not assignable to type 'S'. +tests/cases/compiler/narrowGenericTypeByInstanceOf.ts(143,16): error TS2345: Argument of type 'Parent & Child' is not assignable to parameter of type 'Child'. + Types of property 'value3' are incompatible. + Type 'S | T' is not assignable to type 'T'. + Type 'S' is not assignable to type 'T'. +tests/cases/compiler/narrowGenericTypeByInstanceOf.ts(144,20): error TS2345: Argument of type 'Parent & Child' is not assignable to parameter of type 'Child'. + Types of property 'value3' are incompatible. + Type 'S | T' is not assignable to type 'S & T'. + Type 'S' is not assignable to type 'S & T'. + Type 'S' is not assignable to type 'T'. +tests/cases/compiler/narrowGenericTypeByInstanceOf.ts(177,21): error TS2345: Argument of type 'Child | Child | Child<{ foo: string; }>' is not assignable to parameter of type 'Child'. + Type 'Child' is not assignable to type 'Child'. + Type 'number' is not assignable to type 'string'. +tests/cases/compiler/narrowGenericTypeByInstanceOf.ts(178,21): error TS2345: Argument of type 'Child | Child | Child<{ foo: string; }>' is not assignable to parameter of type 'Child'. + Type 'Child' is not assignable to type 'Child'. + Type 'string' is not assignable to type 'number'. + + +==== tests/cases/compiler/narrowGenericTypeByInstanceOf.ts (14 errors) ==== + import { stringify } from "querystring"; + ~~~~~~~~~~~~~ +!!! error TS2307: Cannot find module 'querystring'. + + function example1() { + class Parent { + value: T; + } + + class Child extends Parent { + other: T; + } + + const obj = new Parent(); + + function onlyChildNumber(child: Child) { + // no-op + } + function onlyChildString(child: Child) { + // no-op + } + + if (obj instanceof Child) { + onlyChildNumber(obj); // should PASS + + onlyChildString(obj); // should ERROR: Child is not assignable to Child. + ~~~ +!!! error TS2345: Argument of type 'Child' is not assignable to parameter of type 'Child'. +!!! error TS2345: Type 'number' is not assignable to type 'string'. + } + } + function example2() { + class Parent { + value1: A; + value2: B; + } + + class Child extends Parent { + other: T; + } + + const obj = new Parent(); + + function onlyChildNumber(child: Child) { + // no-op + } + function onlyChildString(child: Child) { + // no-op + } + + if (obj instanceof Child) { + onlyChildNumber(obj); // should PASS + + onlyChildString(obj); // should ERROR: Child is not assignable to Child. + ~~~ +!!! error TS2345: Argument of type 'Child' is not assignable to parameter of type 'Child'. +!!! error TS2345: Type 'number' is not assignable to type 'string'. + } + } + + function example3() { + class Parent { + value1: A; + value2: B; + } + + class Child extends Parent { + value3: C; + value4: D; + } + + const obj = new Parent(); + + function onlyChildNumberString(child: Child) { + // no-op + } + function onlyChildStringNumber(child: Child) { + // no-op + } + function onlyChildNumberNumber(child: Child) { + // no-op + } + + if (obj instanceof Child) { + onlyChildNumberString(obj); // should ERROR: Child is not assignable to Child. + ~~~ +!!! error TS2345: Argument of type 'Child' is not assignable to parameter of type 'Child'. +!!! error TS2345: Type 'string' is not assignable to type 'number'. + onlyChildNumberNumber(obj); // should ERROR: Child is not assignable to Child. + + onlyChildStringNumber(obj); // should PASS + } + } + + function example4() { + class Parent { + value1: A; + value2: B; + } + + class Child extends Parent { + value3: C; + } + + const obj1 = new Parent(); + const obj2 = new Parent(); + + function onlyChildNumber(child: Child) { + // no-op + } + function onlyChildString(child: Child) { + // no-op + } + function onlyChildStringAndNumber(child: Child) { + // no-op + } + + if (obj1 instanceof Child) { + onlyChildNumber(obj1); + ~~~~ +!!! error TS2345: Argument of type 'Parent & Child' is not assignable to parameter of type 'Child'. +!!! error TS2345: Types of property 'value3' are incompatible. +!!! error TS2345: Type 'string | number' is not assignable to type 'number'. +!!! error TS2345: Type 'string' is not assignable to type 'number'. + onlyChildString(obj1); + ~~~~ +!!! error TS2345: Argument of type 'Parent & Child' is not assignable to parameter of type 'Child'. +!!! error TS2345: Types of property 'value3' are incompatible. +!!! error TS2345: Type 'string | number' is not assignable to type 'string'. +!!! error TS2345: Type 'number' is not assignable to type 'string'. + onlyChildStringAndNumber(obj1); + ~~~~ +!!! error TS2345: Argument of type 'Parent & Child' is not assignable to parameter of type 'Child'. +!!! error TS2345: Types of property 'value3' are incompatible. +!!! error TS2345: Type 'string | number' is not assignable to type 'string & number'. +!!! error TS2345: Type 'string' is not assignable to type 'string & number'. +!!! error TS2345: Type 'string' is not assignable to type 'number'. + } + if (obj2 instanceof Child) { + onlyChildNumber(obj2); + onlyChildString(obj2); + ~~~~ +!!! error TS2345: Argument of type 'Child' is not assignable to parameter of type 'Child'. +!!! error TS2345: Type 'number' is not assignable to type 'string'. + onlyChildStringAndNumber(obj2); + ~~~~ +!!! error TS2345: Argument of type 'Child' is not assignable to parameter of type 'Child'. +!!! error TS2345: Type 'number' is not assignable to type 'string & number'. +!!! error TS2345: Type 'number' is not assignable to type 'string'. + } + } + + function example5() { + class Parent { + value1: A; + value2: B; + } + + class Child extends Parent { + value3: C; + } + + const obj = new Parent(); + + function onlyChildS(child: Child) { + // no-op + } + function onlyChildT(child: Child) { + // no-op + } + function onlyChildSAndT(child: Child) { + // no-op + } + + if (obj instanceof Child) { + onlyChildS(obj); + ~~~ +!!! error TS2345: Argument of type 'Parent & Child' is not assignable to parameter of type 'Child'. +!!! error TS2345: Types of property 'value3' are incompatible. +!!! error TS2345: Type 'S | T' is not assignable to type 'S'. +!!! error TS2345: Type 'T' is not assignable to type 'S'. + onlyChildT(obj); + ~~~ +!!! error TS2345: Argument of type 'Parent & Child' is not assignable to parameter of type 'Child'. +!!! error TS2345: Types of property 'value3' are incompatible. +!!! error TS2345: Type 'S | T' is not assignable to type 'T'. +!!! error TS2345: Type 'S' is not assignable to type 'T'. + onlyChildSAndT(obj); + ~~~ +!!! error TS2345: Argument of type 'Parent & Child' is not assignable to parameter of type 'Child'. +!!! error TS2345: Types of property 'value3' are incompatible. +!!! error TS2345: Type 'S | T' is not assignable to type 'S & T'. +!!! error TS2345: Type 'S' is not assignable to type 'S & T'. +!!! error TS2345: Type 'S' is not assignable to type 'T'. + } + } + + function example6() { + class Parent { + value1: A; + value2: B; + } + + class Child extends Parent { + value3: C; + } + + const obj: + | Parent<{ foo: string }, { foo: string }> + | Parent + | Parent = undefined as any; + + const obj1 = undefined as Parent<{ foo: string }, { foo: string }>; + const obj2 = undefined as Parent; + const obj3 = undefined as Parent; + const obj4 = undefined as string | { foo: string }; + const obj5 = undefined as { foo: string }; + + function onlyChildString(child: Child) { + // no-op + } + function onlyChildNumber(child: Child) { + // no-op + } + + if (obj instanceof Child) { + onlyChildString(obj); + ~~~ +!!! error TS2345: Argument of type 'Child | Child | Child<{ foo: string; }>' is not assignable to parameter of type 'Child'. +!!! error TS2345: Type 'Child' is not assignable to type 'Child'. +!!! error TS2345: Type 'number' is not assignable to type 'string'. + onlyChildNumber(obj); + ~~~ +!!! error TS2345: Argument of type 'Child | Child | Child<{ foo: string; }>' is not assignable to parameter of type 'Child'. +!!! error TS2345: Type 'Child' is not assignable to type 'Child'. +!!! error TS2345: Type 'string' is not assignable to type 'number'. + } + + if (obj1 instanceof Child) { + console.log(obj1); + } + if (obj2 instanceof Child) { + console.log(obj2); + } + if (obj3 instanceof Child) { + console.log(obj3); + } + if (obj4 instanceof Child) { + console.log(obj4); + } + if (obj5 instanceof Child) { + console.log(obj5); + } + } + + function negative1() { + class Parent { + value1: A; + value2: B; + } + + class Child extends Parent { + value3: C; + } + + const obj: + | Parent + | Parent + | Child = undefined as any; + + if (obj instanceof Child) { + return; + } + + console.log(obj); + } + \ No newline at end of file diff --git a/tests/baselines/reference/narrowGenericTypeByInstanceOf.js b/tests/baselines/reference/narrowGenericTypeByInstanceOf.js new file mode 100644 index 0000000000000..d1241defa49a5 --- /dev/null +++ b/tests/baselines/reference/narrowGenericTypeByInstanceOf.js @@ -0,0 +1,444 @@ +//// [narrowGenericTypeByInstanceOf.ts] +import { stringify } from "querystring"; + +function example1() { + class Parent { + value: T; + } + + class Child extends Parent { + other: T; + } + + const obj = new Parent(); + + function onlyChildNumber(child: Child) { + // no-op + } + function onlyChildString(child: Child) { + // no-op + } + + if (obj instanceof Child) { + onlyChildNumber(obj); // should PASS + + onlyChildString(obj); // should ERROR: Child is not assignable to Child. + } +} +function example2() { + class Parent { + value1: A; + value2: B; + } + + class Child extends Parent { + other: T; + } + + const obj = new Parent(); + + function onlyChildNumber(child: Child) { + // no-op + } + function onlyChildString(child: Child) { + // no-op + } + + if (obj instanceof Child) { + onlyChildNumber(obj); // should PASS + + onlyChildString(obj); // should ERROR: Child is not assignable to Child. + } +} + +function example3() { + class Parent { + value1: A; + value2: B; + } + + class Child extends Parent { + value3: C; + value4: D; + } + + const obj = new Parent(); + + function onlyChildNumberString(child: Child) { + // no-op + } + function onlyChildStringNumber(child: Child) { + // no-op + } + function onlyChildNumberNumber(child: Child) { + // no-op + } + + if (obj instanceof Child) { + onlyChildNumberString(obj); // should ERROR: Child is not assignable to Child. + onlyChildNumberNumber(obj); // should ERROR: Child is not assignable to Child. + + onlyChildStringNumber(obj); // should PASS + } +} + +function example4() { + class Parent { + value1: A; + value2: B; + } + + class Child extends Parent { + value3: C; + } + + const obj1 = new Parent(); + const obj2 = new Parent(); + + function onlyChildNumber(child: Child) { + // no-op + } + function onlyChildString(child: Child) { + // no-op + } + function onlyChildStringAndNumber(child: Child) { + // no-op + } + + if (obj1 instanceof Child) { + onlyChildNumber(obj1); + onlyChildString(obj1); + onlyChildStringAndNumber(obj1); + } + if (obj2 instanceof Child) { + onlyChildNumber(obj2); + onlyChildString(obj2); + onlyChildStringAndNumber(obj2); + } +} + +function example5() { + class Parent { + value1: A; + value2: B; + } + + class Child extends Parent { + value3: C; + } + + const obj = new Parent(); + + function onlyChildS(child: Child) { + // no-op + } + function onlyChildT(child: Child) { + // no-op + } + function onlyChildSAndT(child: Child) { + // no-op + } + + if (obj instanceof Child) { + onlyChildS(obj); + onlyChildT(obj); + onlyChildSAndT(obj); + } +} + +function example6() { + class Parent { + value1: A; + value2: B; + } + + class Child extends Parent { + value3: C; + } + + const obj: + | Parent<{ foo: string }, { foo: string }> + | Parent + | Parent = undefined as any; + + const obj1 = undefined as Parent<{ foo: string }, { foo: string }>; + const obj2 = undefined as Parent; + const obj3 = undefined as Parent; + const obj4 = undefined as string | { foo: string }; + const obj5 = undefined as { foo: string }; + + function onlyChildString(child: Child) { + // no-op + } + function onlyChildNumber(child: Child) { + // no-op + } + + if (obj instanceof Child) { + onlyChildString(obj); + onlyChildNumber(obj); + } + + if (obj1 instanceof Child) { + console.log(obj1); + } + if (obj2 instanceof Child) { + console.log(obj2); + } + if (obj3 instanceof Child) { + console.log(obj3); + } + if (obj4 instanceof Child) { + console.log(obj4); + } + if (obj5 instanceof Child) { + console.log(obj5); + } +} + +function negative1() { + class Parent { + value1: A; + value2: B; + } + + class Child extends Parent { + value3: C; + } + + const obj: + | Parent + | Parent + | Child = undefined as any; + + if (obj instanceof Child) { + return; + } + + console.log(obj); +} + + +//// [narrowGenericTypeByInstanceOf.js] +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = function (d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +exports.__esModule = true; +function example1() { + var Parent = /** @class */ (function () { + function Parent() { + } + return Parent; + }()); + var Child = /** @class */ (function (_super) { + __extends(Child, _super); + function Child() { + return _super !== null && _super.apply(this, arguments) || this; + } + return Child; + }(Parent)); + var obj = new Parent(); + function onlyChildNumber(child) { + // no-op + } + function onlyChildString(child) { + // no-op + } + if (obj instanceof Child) { + onlyChildNumber(obj); // should PASS + onlyChildString(obj); // should ERROR: Child is not assignable to Child. + } +} +function example2() { + var Parent = /** @class */ (function () { + function Parent() { + } + return Parent; + }()); + var Child = /** @class */ (function (_super) { + __extends(Child, _super); + function Child() { + return _super !== null && _super.apply(this, arguments) || this; + } + return Child; + }(Parent)); + var obj = new Parent(); + function onlyChildNumber(child) { + // no-op + } + function onlyChildString(child) { + // no-op + } + if (obj instanceof Child) { + onlyChildNumber(obj); // should PASS + onlyChildString(obj); // should ERROR: Child is not assignable to Child. + } +} +function example3() { + var Parent = /** @class */ (function () { + function Parent() { + } + return Parent; + }()); + var Child = /** @class */ (function (_super) { + __extends(Child, _super); + function Child() { + return _super !== null && _super.apply(this, arguments) || this; + } + return Child; + }(Parent)); + var obj = new Parent(); + function onlyChildNumberString(child) { + // no-op + } + function onlyChildStringNumber(child) { + // no-op + } + function onlyChildNumberNumber(child) { + // no-op + } + if (obj instanceof Child) { + onlyChildNumberString(obj); // should ERROR: Child is not assignable to Child. + onlyChildNumberNumber(obj); // should ERROR: Child is not assignable to Child. + onlyChildStringNumber(obj); // should PASS + } +} +function example4() { + var Parent = /** @class */ (function () { + function Parent() { + } + return Parent; + }()); + var Child = /** @class */ (function (_super) { + __extends(Child, _super); + function Child() { + return _super !== null && _super.apply(this, arguments) || this; + } + return Child; + }(Parent)); + var obj1 = new Parent(); + var obj2 = new Parent(); + function onlyChildNumber(child) { + // no-op + } + function onlyChildString(child) { + // no-op + } + function onlyChildStringAndNumber(child) { + // no-op + } + if (obj1 instanceof Child) { + onlyChildNumber(obj1); + onlyChildString(obj1); + onlyChildStringAndNumber(obj1); + } + if (obj2 instanceof Child) { + onlyChildNumber(obj2); + onlyChildString(obj2); + onlyChildStringAndNumber(obj2); + } +} +function example5() { + var Parent = /** @class */ (function () { + function Parent() { + } + return Parent; + }()); + var Child = /** @class */ (function (_super) { + __extends(Child, _super); + function Child() { + return _super !== null && _super.apply(this, arguments) || this; + } + return Child; + }(Parent)); + var obj = new Parent(); + function onlyChildS(child) { + // no-op + } + function onlyChildT(child) { + // no-op + } + function onlyChildSAndT(child) { + // no-op + } + if (obj instanceof Child) { + onlyChildS(obj); + onlyChildT(obj); + onlyChildSAndT(obj); + } +} +function example6() { + var Parent = /** @class */ (function () { + function Parent() { + } + return Parent; + }()); + var Child = /** @class */ (function (_super) { + __extends(Child, _super); + function Child() { + return _super !== null && _super.apply(this, arguments) || this; + } + return Child; + }(Parent)); + var obj = undefined; + var obj1 = undefined; + var obj2 = undefined; + var obj3 = undefined; + var obj4 = undefined; + var obj5 = undefined; + function onlyChildString(child) { + // no-op + } + function onlyChildNumber(child) { + // no-op + } + if (obj instanceof Child) { + onlyChildString(obj); + onlyChildNumber(obj); + } + if (obj1 instanceof Child) { + console.log(obj1); + } + if (obj2 instanceof Child) { + console.log(obj2); + } + if (obj3 instanceof Child) { + console.log(obj3); + } + if (obj4 instanceof Child) { + console.log(obj4); + } + if (obj5 instanceof Child) { + console.log(obj5); + } +} +function negative1() { + var Parent = /** @class */ (function () { + function Parent() { + } + return Parent; + }()); + var Child = /** @class */ (function (_super) { + __extends(Child, _super); + function Child() { + return _super !== null && _super.apply(this, arguments) || this; + } + return Child; + }(Parent)); + var obj = undefined; + if (obj instanceof Child) { + return; + } + console.log(obj); +} diff --git a/tests/baselines/reference/narrowGenericTypeByInstanceOf.symbols b/tests/baselines/reference/narrowGenericTypeByInstanceOf.symbols new file mode 100644 index 0000000000000..d31ee4276e158 --- /dev/null +++ b/tests/baselines/reference/narrowGenericTypeByInstanceOf.symbols @@ -0,0 +1,580 @@ +=== tests/cases/compiler/narrowGenericTypeByInstanceOf.ts === +import { stringify } from "querystring"; +>stringify : Symbol(stringify, Decl(narrowGenericTypeByInstanceOf.ts, 0, 8)) + +function example1() { +>example1 : Symbol(example1, Decl(narrowGenericTypeByInstanceOf.ts, 0, 40)) + + class Parent { +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 2, 21)) +>T : Symbol(T, Decl(narrowGenericTypeByInstanceOf.ts, 3, 15)) + + value: T; +>value : Symbol(Parent.value, Decl(narrowGenericTypeByInstanceOf.ts, 3, 19)) +>T : Symbol(T, Decl(narrowGenericTypeByInstanceOf.ts, 3, 15)) + } + + class Child extends Parent { +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 5, 3)) +>T : Symbol(T, Decl(narrowGenericTypeByInstanceOf.ts, 7, 14)) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 2, 21)) +>T : Symbol(T, Decl(narrowGenericTypeByInstanceOf.ts, 7, 14)) + + other: T; +>other : Symbol(Child.other, Decl(narrowGenericTypeByInstanceOf.ts, 7, 36)) +>T : Symbol(T, Decl(narrowGenericTypeByInstanceOf.ts, 7, 14)) + } + + const obj = new Parent(); +>obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 11, 7)) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 2, 21)) + + function onlyChildNumber(child: Child) { +>onlyChildNumber : Symbol(onlyChildNumber, Decl(narrowGenericTypeByInstanceOf.ts, 11, 35)) +>child : Symbol(child, Decl(narrowGenericTypeByInstanceOf.ts, 13, 27)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 5, 3)) + + // no-op + } + function onlyChildString(child: Child) { +>onlyChildString : Symbol(onlyChildString, Decl(narrowGenericTypeByInstanceOf.ts, 15, 3)) +>child : Symbol(child, Decl(narrowGenericTypeByInstanceOf.ts, 16, 27)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 5, 3)) + + // no-op + } + + if (obj instanceof Child) { +>obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 11, 7)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 5, 3)) + + onlyChildNumber(obj); // should PASS +>onlyChildNumber : Symbol(onlyChildNumber, Decl(narrowGenericTypeByInstanceOf.ts, 11, 35)) +>obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 11, 7)) + + onlyChildString(obj); // should ERROR: Child is not assignable to Child. +>onlyChildString : Symbol(onlyChildString, Decl(narrowGenericTypeByInstanceOf.ts, 15, 3)) +>obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 11, 7)) + } +} +function example2() { +>example2 : Symbol(example2, Decl(narrowGenericTypeByInstanceOf.ts, 25, 1)) + + class Parent { +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 26, 21)) +>A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 27, 15)) +>B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 27, 17)) + + value1: A; +>value1 : Symbol(Parent.value1, Decl(narrowGenericTypeByInstanceOf.ts, 27, 22)) +>A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 27, 15)) + + value2: B; +>value2 : Symbol(Parent.value2, Decl(narrowGenericTypeByInstanceOf.ts, 28, 14)) +>B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 27, 17)) + } + + class Child extends Parent { +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 30, 3)) +>T : Symbol(T, Decl(narrowGenericTypeByInstanceOf.ts, 32, 14)) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 26, 21)) +>T : Symbol(T, Decl(narrowGenericTypeByInstanceOf.ts, 32, 14)) +>T : Symbol(T, Decl(narrowGenericTypeByInstanceOf.ts, 32, 14)) + + other: T; +>other : Symbol(Child.other, Decl(narrowGenericTypeByInstanceOf.ts, 32, 39)) +>T : Symbol(T, Decl(narrowGenericTypeByInstanceOf.ts, 32, 14)) + } + + const obj = new Parent(); +>obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 36, 7)) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 26, 21)) + + function onlyChildNumber(child: Child) { +>onlyChildNumber : Symbol(onlyChildNumber, Decl(narrowGenericTypeByInstanceOf.ts, 36, 43)) +>child : Symbol(child, Decl(narrowGenericTypeByInstanceOf.ts, 38, 27)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 30, 3)) + + // no-op + } + function onlyChildString(child: Child) { +>onlyChildString : Symbol(onlyChildString, Decl(narrowGenericTypeByInstanceOf.ts, 40, 3)) +>child : Symbol(child, Decl(narrowGenericTypeByInstanceOf.ts, 41, 27)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 30, 3)) + + // no-op + } + + if (obj instanceof Child) { +>obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 36, 7)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 30, 3)) + + onlyChildNumber(obj); // should PASS +>onlyChildNumber : Symbol(onlyChildNumber, Decl(narrowGenericTypeByInstanceOf.ts, 36, 43)) +>obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 36, 7)) + + onlyChildString(obj); // should ERROR: Child is not assignable to Child. +>onlyChildString : Symbol(onlyChildString, Decl(narrowGenericTypeByInstanceOf.ts, 40, 3)) +>obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 36, 7)) + } +} + +function example3() { +>example3 : Symbol(example3, Decl(narrowGenericTypeByInstanceOf.ts, 50, 1)) + + class Parent { +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 52, 21)) +>A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 53, 15)) +>B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 53, 17)) + + value1: A; +>value1 : Symbol(Parent.value1, Decl(narrowGenericTypeByInstanceOf.ts, 53, 22)) +>A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 53, 15)) + + value2: B; +>value2 : Symbol(Parent.value2, Decl(narrowGenericTypeByInstanceOf.ts, 54, 14)) +>B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 53, 17)) + } + + class Child extends Parent { +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 56, 3)) +>C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 58, 14)) +>D : Symbol(D, Decl(narrowGenericTypeByInstanceOf.ts, 58, 16)) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 52, 21)) +>D : Symbol(D, Decl(narrowGenericTypeByInstanceOf.ts, 58, 16)) +>C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 58, 14)) + + value3: C; +>value3 : Symbol(Child.value3, Decl(narrowGenericTypeByInstanceOf.ts, 58, 42)) +>C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 58, 14)) + + value4: D; +>value4 : Symbol(Child.value4, Decl(narrowGenericTypeByInstanceOf.ts, 59, 14)) +>D : Symbol(D, Decl(narrowGenericTypeByInstanceOf.ts, 58, 16)) + } + + const obj = new Parent(); +>obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 63, 7)) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 52, 21)) + + function onlyChildNumberString(child: Child) { +>onlyChildNumberString : Symbol(onlyChildNumberString, Decl(narrowGenericTypeByInstanceOf.ts, 63, 43)) +>child : Symbol(child, Decl(narrowGenericTypeByInstanceOf.ts, 65, 33)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 56, 3)) + + // no-op + } + function onlyChildStringNumber(child: Child) { +>onlyChildStringNumber : Symbol(onlyChildStringNumber, Decl(narrowGenericTypeByInstanceOf.ts, 67, 3)) +>child : Symbol(child, Decl(narrowGenericTypeByInstanceOf.ts, 68, 33)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 56, 3)) + + // no-op + } + function onlyChildNumberNumber(child: Child) { +>onlyChildNumberNumber : Symbol(onlyChildNumberNumber, Decl(narrowGenericTypeByInstanceOf.ts, 70, 3)) +>child : Symbol(child, Decl(narrowGenericTypeByInstanceOf.ts, 71, 33)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 56, 3)) + + // no-op + } + + if (obj instanceof Child) { +>obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 63, 7)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 56, 3)) + + onlyChildNumberString(obj); // should ERROR: Child is not assignable to Child. +>onlyChildNumberString : Symbol(onlyChildNumberString, Decl(narrowGenericTypeByInstanceOf.ts, 63, 43)) +>obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 63, 7)) + + onlyChildNumberNumber(obj); // should ERROR: Child is not assignable to Child. +>onlyChildNumberNumber : Symbol(onlyChildNumberNumber, Decl(narrowGenericTypeByInstanceOf.ts, 70, 3)) +>obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 63, 7)) + + onlyChildStringNumber(obj); // should PASS +>onlyChildStringNumber : Symbol(onlyChildStringNumber, Decl(narrowGenericTypeByInstanceOf.ts, 67, 3)) +>obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 63, 7)) + } +} + +function example4() { +>example4 : Symbol(example4, Decl(narrowGenericTypeByInstanceOf.ts, 81, 1)) + + class Parent { +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 83, 21)) +>A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 84, 15)) +>B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 84, 17)) + + value1: A; +>value1 : Symbol(Parent.value1, Decl(narrowGenericTypeByInstanceOf.ts, 84, 22)) +>A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 84, 15)) + + value2: B; +>value2 : Symbol(Parent.value2, Decl(narrowGenericTypeByInstanceOf.ts, 85, 14)) +>B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 84, 17)) + } + + class Child extends Parent { +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 87, 3)) +>C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 89, 14)) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 83, 21)) +>C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 89, 14)) +>C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 89, 14)) + + value3: C; +>value3 : Symbol(Child.value3, Decl(narrowGenericTypeByInstanceOf.ts, 89, 39)) +>C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 89, 14)) + } + + const obj1 = new Parent(); +>obj1 : Symbol(obj1, Decl(narrowGenericTypeByInstanceOf.ts, 93, 7)) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 83, 21)) + + const obj2 = new Parent(); +>obj2 : Symbol(obj2, Decl(narrowGenericTypeByInstanceOf.ts, 94, 7)) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 83, 21)) + + function onlyChildNumber(child: Child) { +>onlyChildNumber : Symbol(onlyChildNumber, Decl(narrowGenericTypeByInstanceOf.ts, 94, 44)) +>child : Symbol(child, Decl(narrowGenericTypeByInstanceOf.ts, 96, 27)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 87, 3)) + + // no-op + } + function onlyChildString(child: Child) { +>onlyChildString : Symbol(onlyChildString, Decl(narrowGenericTypeByInstanceOf.ts, 98, 3)) +>child : Symbol(child, Decl(narrowGenericTypeByInstanceOf.ts, 99, 27)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 87, 3)) + + // no-op + } + function onlyChildStringAndNumber(child: Child) { +>onlyChildStringAndNumber : Symbol(onlyChildStringAndNumber, Decl(narrowGenericTypeByInstanceOf.ts, 101, 3)) +>child : Symbol(child, Decl(narrowGenericTypeByInstanceOf.ts, 102, 36)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 87, 3)) + + // no-op + } + + if (obj1 instanceof Child) { +>obj1 : Symbol(obj1, Decl(narrowGenericTypeByInstanceOf.ts, 93, 7)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 87, 3)) + + onlyChildNumber(obj1); +>onlyChildNumber : Symbol(onlyChildNumber, Decl(narrowGenericTypeByInstanceOf.ts, 94, 44)) +>obj1 : Symbol(obj1, Decl(narrowGenericTypeByInstanceOf.ts, 93, 7)) + + onlyChildString(obj1); +>onlyChildString : Symbol(onlyChildString, Decl(narrowGenericTypeByInstanceOf.ts, 98, 3)) +>obj1 : Symbol(obj1, Decl(narrowGenericTypeByInstanceOf.ts, 93, 7)) + + onlyChildStringAndNumber(obj1); +>onlyChildStringAndNumber : Symbol(onlyChildStringAndNumber, Decl(narrowGenericTypeByInstanceOf.ts, 101, 3)) +>obj1 : Symbol(obj1, Decl(narrowGenericTypeByInstanceOf.ts, 93, 7)) + } + if (obj2 instanceof Child) { +>obj2 : Symbol(obj2, Decl(narrowGenericTypeByInstanceOf.ts, 94, 7)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 87, 3)) + + onlyChildNumber(obj2); +>onlyChildNumber : Symbol(onlyChildNumber, Decl(narrowGenericTypeByInstanceOf.ts, 94, 44)) +>obj2 : Symbol(obj2, Decl(narrowGenericTypeByInstanceOf.ts, 94, 7)) + + onlyChildString(obj2); +>onlyChildString : Symbol(onlyChildString, Decl(narrowGenericTypeByInstanceOf.ts, 98, 3)) +>obj2 : Symbol(obj2, Decl(narrowGenericTypeByInstanceOf.ts, 94, 7)) + + onlyChildStringAndNumber(obj2); +>onlyChildStringAndNumber : Symbol(onlyChildStringAndNumber, Decl(narrowGenericTypeByInstanceOf.ts, 101, 3)) +>obj2 : Symbol(obj2, Decl(narrowGenericTypeByInstanceOf.ts, 94, 7)) + } +} + +function example5() { +>example5 : Symbol(example5, Decl(narrowGenericTypeByInstanceOf.ts, 116, 1)) +>S : Symbol(S, Decl(narrowGenericTypeByInstanceOf.ts, 118, 18)) +>T : Symbol(T, Decl(narrowGenericTypeByInstanceOf.ts, 118, 20)) + + class Parent { +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 118, 27)) +>A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 119, 15)) +>B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 119, 17)) + + value1: A; +>value1 : Symbol(Parent.value1, Decl(narrowGenericTypeByInstanceOf.ts, 119, 22)) +>A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 119, 15)) + + value2: B; +>value2 : Symbol(Parent.value2, Decl(narrowGenericTypeByInstanceOf.ts, 120, 14)) +>B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 119, 17)) + } + + class Child extends Parent { +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 122, 3)) +>C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 124, 14)) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 118, 27)) +>C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 124, 14)) +>C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 124, 14)) + + value3: C; +>value3 : Symbol(Child.value3, Decl(narrowGenericTypeByInstanceOf.ts, 124, 39)) +>C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 124, 14)) + } + + const obj = new Parent(); +>obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 128, 7)) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 118, 27)) +>S : Symbol(S, Decl(narrowGenericTypeByInstanceOf.ts, 118, 18)) +>T : Symbol(T, Decl(narrowGenericTypeByInstanceOf.ts, 118, 20)) + + function onlyChildS(child: Child) { +>onlyChildS : Symbol(onlyChildS, Decl(narrowGenericTypeByInstanceOf.ts, 128, 33)) +>child : Symbol(child, Decl(narrowGenericTypeByInstanceOf.ts, 130, 22)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 122, 3)) +>S : Symbol(S, Decl(narrowGenericTypeByInstanceOf.ts, 118, 18)) + + // no-op + } + function onlyChildT(child: Child) { +>onlyChildT : Symbol(onlyChildT, Decl(narrowGenericTypeByInstanceOf.ts, 132, 3)) +>child : Symbol(child, Decl(narrowGenericTypeByInstanceOf.ts, 133, 22)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 122, 3)) +>T : Symbol(T, Decl(narrowGenericTypeByInstanceOf.ts, 118, 20)) + + // no-op + } + function onlyChildSAndT(child: Child) { +>onlyChildSAndT : Symbol(onlyChildSAndT, Decl(narrowGenericTypeByInstanceOf.ts, 135, 3)) +>child : Symbol(child, Decl(narrowGenericTypeByInstanceOf.ts, 136, 26)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 122, 3)) +>S : Symbol(S, Decl(narrowGenericTypeByInstanceOf.ts, 118, 18)) +>T : Symbol(T, Decl(narrowGenericTypeByInstanceOf.ts, 118, 20)) + + // no-op + } + + if (obj instanceof Child) { +>obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 128, 7)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 122, 3)) + + onlyChildS(obj); +>onlyChildS : Symbol(onlyChildS, Decl(narrowGenericTypeByInstanceOf.ts, 128, 33)) +>obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 128, 7)) + + onlyChildT(obj); +>onlyChildT : Symbol(onlyChildT, Decl(narrowGenericTypeByInstanceOf.ts, 132, 3)) +>obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 128, 7)) + + onlyChildSAndT(obj); +>onlyChildSAndT : Symbol(onlyChildSAndT, Decl(narrowGenericTypeByInstanceOf.ts, 135, 3)) +>obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 128, 7)) + } +} + +function example6() { +>example6 : Symbol(example6, Decl(narrowGenericTypeByInstanceOf.ts, 145, 1)) + + class Parent { +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 147, 21)) +>A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 148, 15)) +>B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 148, 17)) + + value1: A; +>value1 : Symbol(Parent.value1, Decl(narrowGenericTypeByInstanceOf.ts, 148, 22)) +>A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 148, 15)) + + value2: B; +>value2 : Symbol(Parent.value2, Decl(narrowGenericTypeByInstanceOf.ts, 149, 14)) +>B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 148, 17)) + } + + class Child extends Parent { +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 151, 3)) +>C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 153, 14)) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 147, 21)) +>C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 153, 14)) +>C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 153, 14)) + + value3: C; +>value3 : Symbol(Child.value3, Decl(narrowGenericTypeByInstanceOf.ts, 153, 39)) +>C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 153, 14)) + } + + const obj: +>obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 157, 7)) + + | Parent<{ foo: string }, { foo: string }> +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 147, 21)) +>foo : Symbol(foo, Decl(narrowGenericTypeByInstanceOf.ts, 158, 14)) +>foo : Symbol(foo, Decl(narrowGenericTypeByInstanceOf.ts, 158, 31)) + + | Parent +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 147, 21)) + + | Parent = undefined as any; +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 147, 21)) +>undefined : Symbol(undefined) + + const obj1 = undefined as Parent<{ foo: string }, { foo: string }>; +>obj1 : Symbol(obj1, Decl(narrowGenericTypeByInstanceOf.ts, 162, 7)) +>undefined : Symbol(undefined) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 147, 21)) +>foo : Symbol(foo, Decl(narrowGenericTypeByInstanceOf.ts, 162, 36)) +>foo : Symbol(foo, Decl(narrowGenericTypeByInstanceOf.ts, 162, 53)) + + const obj2 = undefined as Parent; +>obj2 : Symbol(obj2, Decl(narrowGenericTypeByInstanceOf.ts, 163, 7)) +>undefined : Symbol(undefined) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 147, 21)) + + const obj3 = undefined as Parent; +>obj3 : Symbol(obj3, Decl(narrowGenericTypeByInstanceOf.ts, 164, 7)) +>undefined : Symbol(undefined) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 147, 21)) + + const obj4 = undefined as string | { foo: string }; +>obj4 : Symbol(obj4, Decl(narrowGenericTypeByInstanceOf.ts, 165, 7)) +>undefined : Symbol(undefined) +>foo : Symbol(foo, Decl(narrowGenericTypeByInstanceOf.ts, 165, 38)) + + const obj5 = undefined as { foo: string }; +>obj5 : Symbol(obj5, Decl(narrowGenericTypeByInstanceOf.ts, 166, 7)) +>undefined : Symbol(undefined) +>foo : Symbol(foo, Decl(narrowGenericTypeByInstanceOf.ts, 166, 29)) + + function onlyChildString(child: Child) { +>onlyChildString : Symbol(onlyChildString, Decl(narrowGenericTypeByInstanceOf.ts, 166, 44)) +>child : Symbol(child, Decl(narrowGenericTypeByInstanceOf.ts, 168, 27)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 151, 3)) + + // no-op + } + function onlyChildNumber(child: Child) { +>onlyChildNumber : Symbol(onlyChildNumber, Decl(narrowGenericTypeByInstanceOf.ts, 170, 3)) +>child : Symbol(child, Decl(narrowGenericTypeByInstanceOf.ts, 171, 27)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 151, 3)) + + // no-op + } + + if (obj instanceof Child) { +>obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 157, 7)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 151, 3)) + + onlyChildString(obj); +>onlyChildString : Symbol(onlyChildString, Decl(narrowGenericTypeByInstanceOf.ts, 166, 44)) +>obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 157, 7)) + + onlyChildNumber(obj); +>onlyChildNumber : Symbol(onlyChildNumber, Decl(narrowGenericTypeByInstanceOf.ts, 170, 3)) +>obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 157, 7)) + } + + if (obj1 instanceof Child) { +>obj1 : Symbol(obj1, Decl(narrowGenericTypeByInstanceOf.ts, 162, 7)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 151, 3)) + + console.log(obj1); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>obj1 : Symbol(obj1, Decl(narrowGenericTypeByInstanceOf.ts, 162, 7)) + } + if (obj2 instanceof Child) { +>obj2 : Symbol(obj2, Decl(narrowGenericTypeByInstanceOf.ts, 163, 7)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 151, 3)) + + console.log(obj2); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>obj2 : Symbol(obj2, Decl(narrowGenericTypeByInstanceOf.ts, 163, 7)) + } + if (obj3 instanceof Child) { +>obj3 : Symbol(obj3, Decl(narrowGenericTypeByInstanceOf.ts, 164, 7)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 151, 3)) + + console.log(obj3); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>obj3 : Symbol(obj3, Decl(narrowGenericTypeByInstanceOf.ts, 164, 7)) + } + if (obj4 instanceof Child) { +>obj4 : Symbol(obj4, Decl(narrowGenericTypeByInstanceOf.ts, 165, 7)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 151, 3)) + + console.log(obj4); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>obj4 : Symbol(obj4, Decl(narrowGenericTypeByInstanceOf.ts, 165, 7)) + } + if (obj5 instanceof Child) { +>obj5 : Symbol(obj5, Decl(narrowGenericTypeByInstanceOf.ts, 166, 7)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 151, 3)) + + console.log(obj5); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>obj5 : Symbol(obj5, Decl(narrowGenericTypeByInstanceOf.ts, 166, 7)) + } +} + +function negative1() { +>negative1 : Symbol(negative1, Decl(narrowGenericTypeByInstanceOf.ts, 195, 1)) + + class Parent { +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 197, 22)) +>A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 198, 15)) +>B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 198, 17)) + + value1: A; +>value1 : Symbol(Parent.value1, Decl(narrowGenericTypeByInstanceOf.ts, 198, 22)) +>A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 198, 15)) + + value2: B; +>value2 : Symbol(Parent.value2, Decl(narrowGenericTypeByInstanceOf.ts, 199, 14)) +>B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 198, 17)) + } + + class Child extends Parent { +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 201, 3)) +>C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 203, 14)) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 197, 22)) +>C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 203, 14)) +>C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 203, 14)) + + value3: C; +>value3 : Symbol(Child.value3, Decl(narrowGenericTypeByInstanceOf.ts, 203, 39)) +>C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 203, 14)) + } + + const obj: +>obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 207, 7)) + + | Parent +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 197, 22)) + + | Parent +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 197, 22)) + + | Child = undefined as any; +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 201, 3)) +>undefined : Symbol(undefined) + + if (obj instanceof Child) { +>obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 207, 7)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 201, 3)) + + return; + } + + console.log(obj); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 207, 7)) +} + diff --git a/tests/baselines/reference/narrowGenericTypeByInstanceOf.types b/tests/baselines/reference/narrowGenericTypeByInstanceOf.types new file mode 100644 index 0000000000000..419b2c7254e3c --- /dev/null +++ b/tests/baselines/reference/narrowGenericTypeByInstanceOf.types @@ -0,0 +1,540 @@ +=== tests/cases/compiler/narrowGenericTypeByInstanceOf.ts === +import { stringify } from "querystring"; +>stringify : any + +function example1() { +>example1 : () => void + + class Parent { +>Parent : Parent + + value: T; +>value : T + } + + class Child extends Parent { +>Child : Child +>Parent : Parent + + other: T; +>other : T + } + + const obj = new Parent(); +>obj : Parent +>new Parent() : Parent +>Parent : typeof Parent + + function onlyChildNumber(child: Child) { +>onlyChildNumber : (child: Child) => void +>child : Child + + // no-op + } + function onlyChildString(child: Child) { +>onlyChildString : (child: Child) => void +>child : Child + + // no-op + } + + if (obj instanceof Child) { +>obj instanceof Child : boolean +>obj : Parent +>Child : typeof Child + + onlyChildNumber(obj); // should PASS +>onlyChildNumber(obj) : void +>onlyChildNumber : (child: Child) => void +>obj : Child + + onlyChildString(obj); // should ERROR: Child is not assignable to Child. +>onlyChildString(obj) : void +>onlyChildString : (child: Child) => void +>obj : Child + } +} +function example2() { +>example2 : () => void + + class Parent { +>Parent : Parent + + value1: A; +>value1 : A + + value2: B; +>value2 : B + } + + class Child extends Parent { +>Child : Child +>Parent : Parent + + other: T; +>other : T + } + + const obj = new Parent(); +>obj : Parent +>new Parent() : Parent +>Parent : typeof Parent + + function onlyChildNumber(child: Child) { +>onlyChildNumber : (child: Child) => void +>child : Child + + // no-op + } + function onlyChildString(child: Child) { +>onlyChildString : (child: Child) => void +>child : Child + + // no-op + } + + if (obj instanceof Child) { +>obj instanceof Child : boolean +>obj : Parent +>Child : typeof Child + + onlyChildNumber(obj); // should PASS +>onlyChildNumber(obj) : void +>onlyChildNumber : (child: Child) => void +>obj : Child + + onlyChildString(obj); // should ERROR: Child is not assignable to Child. +>onlyChildString(obj) : void +>onlyChildString : (child: Child) => void +>obj : Child + } +} + +function example3() { +>example3 : () => void + + class Parent { +>Parent : Parent + + value1: A; +>value1 : A + + value2: B; +>value2 : B + } + + class Child extends Parent { +>Child : Child +>Parent : Parent + + value3: C; +>value3 : C + + value4: D; +>value4 : D + } + + const obj = new Parent(); +>obj : Parent +>new Parent() : Parent +>Parent : typeof Parent + + function onlyChildNumberString(child: Child) { +>onlyChildNumberString : (child: Child) => void +>child : Child + + // no-op + } + function onlyChildStringNumber(child: Child) { +>onlyChildStringNumber : (child: Child) => void +>child : Child + + // no-op + } + function onlyChildNumberNumber(child: Child) { +>onlyChildNumberNumber : (child: Child) => void +>child : Child + + // no-op + } + + if (obj instanceof Child) { +>obj instanceof Child : boolean +>obj : Parent +>Child : typeof Child + + onlyChildNumberString(obj); // should ERROR: Child is not assignable to Child. +>onlyChildNumberString(obj) : void +>onlyChildNumberString : (child: Child) => void +>obj : Child + + onlyChildNumberNumber(obj); // should ERROR: Child is not assignable to Child. +>onlyChildNumberNumber(obj) : void +>onlyChildNumberNumber : (child: Child) => void +>obj : Child + + onlyChildStringNumber(obj); // should PASS +>onlyChildStringNumber(obj) : void +>onlyChildStringNumber : (child: Child) => void +>obj : Child + } +} + +function example4() { +>example4 : () => void + + class Parent { +>Parent : Parent + + value1: A; +>value1 : A + + value2: B; +>value2 : B + } + + class Child extends Parent { +>Child : Child +>Parent : Parent + + value3: C; +>value3 : C + } + + const obj1 = new Parent(); +>obj1 : Parent +>new Parent() : Parent +>Parent : typeof Parent + + const obj2 = new Parent(); +>obj2 : Parent +>new Parent() : Parent +>Parent : typeof Parent + + function onlyChildNumber(child: Child) { +>onlyChildNumber : (child: Child) => void +>child : Child + + // no-op + } + function onlyChildString(child: Child) { +>onlyChildString : (child: Child) => void +>child : Child + + // no-op + } + function onlyChildStringAndNumber(child: Child) { +>onlyChildStringAndNumber : (child: Child) => void +>child : Child + + // no-op + } + + if (obj1 instanceof Child) { +>obj1 instanceof Child : boolean +>obj1 : Parent +>Child : typeof Child + + onlyChildNumber(obj1); +>onlyChildNumber(obj1) : void +>onlyChildNumber : (child: Child) => void +>obj1 : Parent & Child + + onlyChildString(obj1); +>onlyChildString(obj1) : void +>onlyChildString : (child: Child) => void +>obj1 : Parent & Child + + onlyChildStringAndNumber(obj1); +>onlyChildStringAndNumber(obj1) : void +>onlyChildStringAndNumber : (child: Child) => void +>obj1 : Parent & Child + } + if (obj2 instanceof Child) { +>obj2 instanceof Child : boolean +>obj2 : Parent +>Child : typeof Child + + onlyChildNumber(obj2); +>onlyChildNumber(obj2) : void +>onlyChildNumber : (child: Child) => void +>obj2 : Child + + onlyChildString(obj2); +>onlyChildString(obj2) : void +>onlyChildString : (child: Child) => void +>obj2 : Child + + onlyChildStringAndNumber(obj2); +>onlyChildStringAndNumber(obj2) : void +>onlyChildStringAndNumber : (child: Child) => void +>obj2 : Child + } +} + +function example5() { +>example5 : () => void + + class Parent { +>Parent : Parent + + value1: A; +>value1 : A + + value2: B; +>value2 : B + } + + class Child extends Parent { +>Child : Child +>Parent : Parent + + value3: C; +>value3 : C + } + + const obj = new Parent(); +>obj : Parent +>new Parent() : Parent +>Parent : typeof Parent + + function onlyChildS(child: Child) { +>onlyChildS : (child: Child) => void +>child : Child + + // no-op + } + function onlyChildT(child: Child) { +>onlyChildT : (child: Child) => void +>child : Child + + // no-op + } + function onlyChildSAndT(child: Child) { +>onlyChildSAndT : (child: Child) => void +>child : Child + + // no-op + } + + if (obj instanceof Child) { +>obj instanceof Child : boolean +>obj : Parent +>Child : typeof Child + + onlyChildS(obj); +>onlyChildS(obj) : void +>onlyChildS : (child: Child) => void +>obj : Parent & Child + + onlyChildT(obj); +>onlyChildT(obj) : void +>onlyChildT : (child: Child) => void +>obj : Parent & Child + + onlyChildSAndT(obj); +>onlyChildSAndT(obj) : void +>onlyChildSAndT : (child: Child) => void +>obj : Parent & Child + } +} + +function example6() { +>example6 : () => void + + class Parent { +>Parent : Parent + + value1: A; +>value1 : A + + value2: B; +>value2 : B + } + + class Child extends Parent { +>Child : Child +>Parent : Parent + + value3: C; +>value3 : C + } + + const obj: +>obj : Parent<{ foo: string; }, { foo: string; }> | Parent | Parent + + | Parent<{ foo: string }, { foo: string }> +>foo : string +>foo : string + + | Parent + | Parent = undefined as any; +>undefined as any : any +>undefined : undefined + + const obj1 = undefined as Parent<{ foo: string }, { foo: string }>; +>obj1 : Parent<{ foo: string; }, { foo: string; }> +>undefined as Parent<{ foo: string }, { foo: string }> : Parent<{ foo: string; }, { foo: string; }> +>undefined : undefined +>foo : string +>foo : string + + const obj2 = undefined as Parent; +>obj2 : Parent +>undefined as Parent : Parent +>undefined : undefined + + const obj3 = undefined as Parent; +>obj3 : Parent +>undefined as Parent : Parent +>undefined : undefined + + const obj4 = undefined as string | { foo: string }; +>obj4 : string | { foo: string; } +>undefined as string | { foo: string } : string | { foo: string; } +>undefined : undefined +>foo : string + + const obj5 = undefined as { foo: string }; +>obj5 : { foo: string; } +>undefined as { foo: string } : { foo: string; } +>undefined : undefined +>foo : string + + function onlyChildString(child: Child) { +>onlyChildString : (child: Child) => void +>child : Child + + // no-op + } + function onlyChildNumber(child: Child) { +>onlyChildNumber : (child: Child) => void +>child : Child + + // no-op + } + + if (obj instanceof Child) { +>obj instanceof Child : boolean +>obj : Parent<{ foo: string; }, { foo: string; }> | Parent | Parent +>Child : typeof Child + + onlyChildString(obj); +>onlyChildString(obj) : void +>onlyChildString : (child: Child) => void +>obj : Child | Child | Child<{ foo: string; }> + + onlyChildNumber(obj); +>onlyChildNumber(obj) : void +>onlyChildNumber : (child: Child) => void +>obj : Child | Child | Child<{ foo: string; }> + } + + if (obj1 instanceof Child) { +>obj1 instanceof Child : boolean +>obj1 : Parent<{ foo: string; }, { foo: string; }> +>Child : typeof Child + + console.log(obj1); +>console.log(obj1) : void +>console.log : (message?: any, ...optionalParams: any[]) => void +>console : Console +>log : (message?: any, ...optionalParams: any[]) => void +>obj1 : Child<{ foo: string; }> + } + if (obj2 instanceof Child) { +>obj2 instanceof Child : boolean +>obj2 : Parent +>Child : typeof Child + + console.log(obj2); +>console.log(obj2) : void +>console.log : (message?: any, ...optionalParams: any[]) => void +>console : Console +>log : (message?: any, ...optionalParams: any[]) => void +>obj2 : Child + } + if (obj3 instanceof Child) { +>obj3 instanceof Child : boolean +>obj3 : Parent +>Child : typeof Child + + console.log(obj3); +>console.log(obj3) : void +>console.log : (message?: any, ...optionalParams: any[]) => void +>console : Console +>log : (message?: any, ...optionalParams: any[]) => void +>obj3 : Child + } + if (obj4 instanceof Child) { +>obj4 instanceof Child : boolean +>obj4 : string | { foo: string; } +>Child : typeof Child + + console.log(obj4); +>console.log(obj4) : void +>console.log : (message?: any, ...optionalParams: any[]) => void +>console : Console +>log : (message?: any, ...optionalParams: any[]) => void +>obj4 : (string & Child) | ({ foo: string; } & Child) + } + if (obj5 instanceof Child) { +>obj5 instanceof Child : boolean +>obj5 : { foo: string; } +>Child : typeof Child + + console.log(obj5); +>console.log(obj5) : void +>console.log : (message?: any, ...optionalParams: any[]) => void +>console : Console +>log : (message?: any, ...optionalParams: any[]) => void +>obj5 : { foo: string; } & Child + } +} + +function negative1() { +>negative1 : () => void + + class Parent { +>Parent : Parent + + value1: A; +>value1 : A + + value2: B; +>value2 : B + } + + class Child extends Parent { +>Child : Child +>Parent : Parent + + value3: C; +>value3 : C + } + + const obj: +>obj : Parent | Parent | Child + + | Parent + | Parent + | Child = undefined as any; +>undefined as any : any +>undefined : undefined + + if (obj instanceof Child) { +>obj instanceof Child : boolean +>obj : Parent | Parent | Child +>Child : typeof Child + + return; + } + + console.log(obj); +>console.log(obj) : void +>console.log : (message?: any, ...optionalParams: any[]) => void +>console : Console +>log : (message?: any, ...optionalParams: any[]) => void +>obj : Parent | Parent +} + diff --git a/tests/cases/compiler/narrowGenericTypeByInstanceOf.ts b/tests/cases/compiler/narrowGenericTypeByInstanceOf.ts new file mode 100644 index 0000000000000..2fce122aa7faf --- /dev/null +++ b/tests/cases/compiler/narrowGenericTypeByInstanceOf.ts @@ -0,0 +1,218 @@ +import { stringify } from "querystring"; + +function example1() { + class Parent { + value: T; + } + + class Child extends Parent { + other: T; + } + + const obj = new Parent(); + + function onlyChildNumber(child: Child) { + // no-op + } + function onlyChildString(child: Child) { + // no-op + } + + if (obj instanceof Child) { + onlyChildNumber(obj); // should PASS + + onlyChildString(obj); // should ERROR: Child is not assignable to Child. + } +} +function example2() { + class Parent { + value1: A; + value2: B; + } + + class Child extends Parent { + other: T; + } + + const obj = new Parent(); + + function onlyChildNumber(child: Child) { + // no-op + } + function onlyChildString(child: Child) { + // no-op + } + + if (obj instanceof Child) { + onlyChildNumber(obj); // should PASS + + onlyChildString(obj); // should ERROR: Child is not assignable to Child. + } +} + +function example3() { + class Parent { + value1: A; + value2: B; + } + + class Child extends Parent { + value3: C; + value4: D; + } + + const obj = new Parent(); + + function onlyChildNumberString(child: Child) { + // no-op + } + function onlyChildStringNumber(child: Child) { + // no-op + } + function onlyChildNumberNumber(child: Child) { + // no-op + } + + if (obj instanceof Child) { + onlyChildNumberString(obj); // should ERROR: Child is not assignable to Child. + onlyChildNumberNumber(obj); // should ERROR: Child is not assignable to Child. + + onlyChildStringNumber(obj); // should PASS + } +} + +function example4() { + class Parent { + value1: A; + value2: B; + } + + class Child extends Parent { + value3: C; + } + + const obj1 = new Parent(); + const obj2 = new Parent(); + + function onlyChildNumber(child: Child) { + // no-op + } + function onlyChildString(child: Child) { + // no-op + } + function onlyChildStringAndNumber(child: Child) { + // no-op + } + + if (obj1 instanceof Child) { + onlyChildNumber(obj1); + onlyChildString(obj1); + onlyChildStringAndNumber(obj1); + } + if (obj2 instanceof Child) { + onlyChildNumber(obj2); + onlyChildString(obj2); + onlyChildStringAndNumber(obj2); + } +} + +function example5() { + class Parent { + value1: A; + value2: B; + } + + class Child extends Parent { + value3: C; + } + + const obj = new Parent(); + + function onlyChildS(child: Child) { + // no-op + } + function onlyChildT(child: Child) { + // no-op + } + function onlyChildSAndT(child: Child) { + // no-op + } + + if (obj instanceof Child) { + onlyChildS(obj); + onlyChildT(obj); + onlyChildSAndT(obj); + } +} + +function example6() { + class Parent { + value1: A; + value2: B; + } + + class Child extends Parent { + value3: C; + } + + const obj: + | Parent<{ foo: string }, { foo: string }> + | Parent + | Parent = undefined as any; + + const obj1 = undefined as Parent<{ foo: string }, { foo: string }>; + const obj2 = undefined as Parent; + const obj3 = undefined as Parent; + const obj4 = undefined as string | { foo: string }; + const obj5 = undefined as { foo: string }; + + function onlyChildString(child: Child) { + // no-op + } + function onlyChildNumber(child: Child) { + // no-op + } + + if (obj instanceof Child) { + onlyChildString(obj); + onlyChildNumber(obj); + } + + if (obj1 instanceof Child) { + console.log(obj1); + } + if (obj2 instanceof Child) { + console.log(obj2); + } + if (obj3 instanceof Child) { + console.log(obj3); + } + if (obj4 instanceof Child) { + console.log(obj4); + } + if (obj5 instanceof Child) { + console.log(obj5); + } +} + +function negative1() { + class Parent { + value1: A; + value2: B; + } + + class Child extends Parent { + value3: C; + } + + const obj: + | Parent + | Parent + | Child = undefined as any; + + if (obj instanceof Child) { + return; + } + + console.log(obj); +} From 1067f190a3fceb1cc95ba3564a0c57e4c3abd6e7 Mon Sep 17 00:00:00 2001 From: Nathan Fenner Date: Fri, 22 Feb 2019 13:50:35 -0800 Subject: [PATCH 2/5] narrow by instanceof: restrict generic narrowing to cases where it works well --- src/compiler/checker.ts | 15 +- .../narrowGenericTypeByInstanceOf.errors.txt | 324 -------- .../narrowGenericTypeByInstanceOf.js | 356 ++++----- .../narrowGenericTypeByInstanceOf.symbols | 718 ++++++++---------- .../narrowGenericTypeByInstanceOf.types | 478 +++++------- .../compiler/narrowGenericTypeByInstanceOf.ts | 189 ++--- 6 files changed, 690 insertions(+), 1390 deletions(-) delete mode 100644 tests/baselines/reference/narrowGenericTypeByInstanceOf.errors.txt diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f9cb78d14b545..db546c3247e8e 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -16067,14 +16067,17 @@ namespace ts { const inferenceContext = createInferenceContext( childTypeParameters, childConstructor, - InferenceFlags.AnyDefault, // TODO: we might consider stricter flags in the future + InferenceFlags.NoDefault, // exclude defaults values from inference, since they don't participate in actual typing here. ); // Infer the types from superType onto the return type of the child constructor. inferTypes(inferenceContext.inferences, superType, getReturnTypeOfSignature(childConstructor), InferencePriority.ReturnType); // We extract the inferred arguments from the inference context. - const childArguments = getInferredTypes(inferenceContext); + // silentNeverType indicates that no type could be inferred. + // In these cases, falling back on any produces the simplest user experience. + const childArguments = getInferredTypes(inferenceContext).map(type => type === silentNeverType ? anyType : type); + // Lastly, supply the childType with the new parameters. return instantiateType(getReturnTypeOfSignature(childConstructor), param => { @@ -16158,8 +16161,12 @@ namespace ts { } const narrowedGenericClassTypeCandidate = narrowTypeParametersByAssignability(type, rightType); - if (narrowedGenericClassTypeCandidate && !(narrowedGenericClassTypeCandidate.flags & TypeFlags.Never)) { - // When applicable, this overrides the basic target. + if (narrowedGenericClassTypeCandidate && !(narrowedGenericClassTypeCandidate.flags & TypeFlags.Never) && isTypeSubtypeOf(narrowedGenericClassTypeCandidate, type)) { + // When the resulting narrowed type is actually a subtype of the original, the candidate it used. + // In some cases, this fail (due to apparent non-inhabitedness). + // For example, if Child extends Parent and we narrow Parent to Child, + // we'll end up with a candidate Child which fails to be a subtype of Parent. + // In this case, we skip updating the target type. targetType = narrowedGenericClassTypeCandidate; } } diff --git a/tests/baselines/reference/narrowGenericTypeByInstanceOf.errors.txt b/tests/baselines/reference/narrowGenericTypeByInstanceOf.errors.txt deleted file mode 100644 index 3b98c6edc9354..0000000000000 --- a/tests/baselines/reference/narrowGenericTypeByInstanceOf.errors.txt +++ /dev/null @@ -1,324 +0,0 @@ -tests/cases/compiler/narrowGenericTypeByInstanceOf.ts(1,27): error TS2307: Cannot find module 'querystring'. -tests/cases/compiler/narrowGenericTypeByInstanceOf.ts(24,21): error TS2345: Argument of type 'Child' is not assignable to parameter of type 'Child'. - Type 'number' is not assignable to type 'string'. -tests/cases/compiler/narrowGenericTypeByInstanceOf.ts(49,21): error TS2345: Argument of type 'Child' is not assignable to parameter of type 'Child'. - Type 'number' is not assignable to type 'string'. -tests/cases/compiler/narrowGenericTypeByInstanceOf.ts(77,27): error TS2345: Argument of type 'Child' is not assignable to parameter of type 'Child'. - Type 'string' is not assignable to type 'number'. -tests/cases/compiler/narrowGenericTypeByInstanceOf.ts(108,21): error TS2345: Argument of type 'Parent & Child' is not assignable to parameter of type 'Child'. - Types of property 'value3' are incompatible. - Type 'string | number' is not assignable to type 'number'. - Type 'string' is not assignable to type 'number'. -tests/cases/compiler/narrowGenericTypeByInstanceOf.ts(109,21): error TS2345: Argument of type 'Parent & Child' is not assignable to parameter of type 'Child'. - Types of property 'value3' are incompatible. - Type 'string | number' is not assignable to type 'string'. - Type 'number' is not assignable to type 'string'. -tests/cases/compiler/narrowGenericTypeByInstanceOf.ts(110,30): error TS2345: Argument of type 'Parent & Child' is not assignable to parameter of type 'Child'. - Types of property 'value3' are incompatible. - Type 'string | number' is not assignable to type 'string & number'. - Type 'string' is not assignable to type 'string & number'. - Type 'string' is not assignable to type 'number'. -tests/cases/compiler/narrowGenericTypeByInstanceOf.ts(114,21): error TS2345: Argument of type 'Child' is not assignable to parameter of type 'Child'. - Type 'number' is not assignable to type 'string'. -tests/cases/compiler/narrowGenericTypeByInstanceOf.ts(115,30): error TS2345: Argument of type 'Child' is not assignable to parameter of type 'Child'. - Type 'number' is not assignable to type 'string & number'. - Type 'number' is not assignable to type 'string'. -tests/cases/compiler/narrowGenericTypeByInstanceOf.ts(142,16): error TS2345: Argument of type 'Parent & Child' is not assignable to parameter of type 'Child'. - Types of property 'value3' are incompatible. - Type 'S | T' is not assignable to type 'S'. - Type 'T' is not assignable to type 'S'. -tests/cases/compiler/narrowGenericTypeByInstanceOf.ts(143,16): error TS2345: Argument of type 'Parent & Child' is not assignable to parameter of type 'Child'. - Types of property 'value3' are incompatible. - Type 'S | T' is not assignable to type 'T'. - Type 'S' is not assignable to type 'T'. -tests/cases/compiler/narrowGenericTypeByInstanceOf.ts(144,20): error TS2345: Argument of type 'Parent & Child' is not assignable to parameter of type 'Child'. - Types of property 'value3' are incompatible. - Type 'S | T' is not assignable to type 'S & T'. - Type 'S' is not assignable to type 'S & T'. - Type 'S' is not assignable to type 'T'. -tests/cases/compiler/narrowGenericTypeByInstanceOf.ts(177,21): error TS2345: Argument of type 'Child | Child | Child<{ foo: string; }>' is not assignable to parameter of type 'Child'. - Type 'Child' is not assignable to type 'Child'. - Type 'number' is not assignable to type 'string'. -tests/cases/compiler/narrowGenericTypeByInstanceOf.ts(178,21): error TS2345: Argument of type 'Child | Child | Child<{ foo: string; }>' is not assignable to parameter of type 'Child'. - Type 'Child' is not assignable to type 'Child'. - Type 'string' is not assignable to type 'number'. - - -==== tests/cases/compiler/narrowGenericTypeByInstanceOf.ts (14 errors) ==== - import { stringify } from "querystring"; - ~~~~~~~~~~~~~ -!!! error TS2307: Cannot find module 'querystring'. - - function example1() { - class Parent { - value: T; - } - - class Child extends Parent { - other: T; - } - - const obj = new Parent(); - - function onlyChildNumber(child: Child) { - // no-op - } - function onlyChildString(child: Child) { - // no-op - } - - if (obj instanceof Child) { - onlyChildNumber(obj); // should PASS - - onlyChildString(obj); // should ERROR: Child is not assignable to Child. - ~~~ -!!! error TS2345: Argument of type 'Child' is not assignable to parameter of type 'Child'. -!!! error TS2345: Type 'number' is not assignable to type 'string'. - } - } - function example2() { - class Parent { - value1: A; - value2: B; - } - - class Child extends Parent { - other: T; - } - - const obj = new Parent(); - - function onlyChildNumber(child: Child) { - // no-op - } - function onlyChildString(child: Child) { - // no-op - } - - if (obj instanceof Child) { - onlyChildNumber(obj); // should PASS - - onlyChildString(obj); // should ERROR: Child is not assignable to Child. - ~~~ -!!! error TS2345: Argument of type 'Child' is not assignable to parameter of type 'Child'. -!!! error TS2345: Type 'number' is not assignable to type 'string'. - } - } - - function example3() { - class Parent { - value1: A; - value2: B; - } - - class Child extends Parent { - value3: C; - value4: D; - } - - const obj = new Parent(); - - function onlyChildNumberString(child: Child) { - // no-op - } - function onlyChildStringNumber(child: Child) { - // no-op - } - function onlyChildNumberNumber(child: Child) { - // no-op - } - - if (obj instanceof Child) { - onlyChildNumberString(obj); // should ERROR: Child is not assignable to Child. - ~~~ -!!! error TS2345: Argument of type 'Child' is not assignable to parameter of type 'Child'. -!!! error TS2345: Type 'string' is not assignable to type 'number'. - onlyChildNumberNumber(obj); // should ERROR: Child is not assignable to Child. - - onlyChildStringNumber(obj); // should PASS - } - } - - function example4() { - class Parent { - value1: A; - value2: B; - } - - class Child extends Parent { - value3: C; - } - - const obj1 = new Parent(); - const obj2 = new Parent(); - - function onlyChildNumber(child: Child) { - // no-op - } - function onlyChildString(child: Child) { - // no-op - } - function onlyChildStringAndNumber(child: Child) { - // no-op - } - - if (obj1 instanceof Child) { - onlyChildNumber(obj1); - ~~~~ -!!! error TS2345: Argument of type 'Parent & Child' is not assignable to parameter of type 'Child'. -!!! error TS2345: Types of property 'value3' are incompatible. -!!! error TS2345: Type 'string | number' is not assignable to type 'number'. -!!! error TS2345: Type 'string' is not assignable to type 'number'. - onlyChildString(obj1); - ~~~~ -!!! error TS2345: Argument of type 'Parent & Child' is not assignable to parameter of type 'Child'. -!!! error TS2345: Types of property 'value3' are incompatible. -!!! error TS2345: Type 'string | number' is not assignable to type 'string'. -!!! error TS2345: Type 'number' is not assignable to type 'string'. - onlyChildStringAndNumber(obj1); - ~~~~ -!!! error TS2345: Argument of type 'Parent & Child' is not assignable to parameter of type 'Child'. -!!! error TS2345: Types of property 'value3' are incompatible. -!!! error TS2345: Type 'string | number' is not assignable to type 'string & number'. -!!! error TS2345: Type 'string' is not assignable to type 'string & number'. -!!! error TS2345: Type 'string' is not assignable to type 'number'. - } - if (obj2 instanceof Child) { - onlyChildNumber(obj2); - onlyChildString(obj2); - ~~~~ -!!! error TS2345: Argument of type 'Child' is not assignable to parameter of type 'Child'. -!!! error TS2345: Type 'number' is not assignable to type 'string'. - onlyChildStringAndNumber(obj2); - ~~~~ -!!! error TS2345: Argument of type 'Child' is not assignable to parameter of type 'Child'. -!!! error TS2345: Type 'number' is not assignable to type 'string & number'. -!!! error TS2345: Type 'number' is not assignable to type 'string'. - } - } - - function example5() { - class Parent { - value1: A; - value2: B; - } - - class Child extends Parent { - value3: C; - } - - const obj = new Parent(); - - function onlyChildS(child: Child) { - // no-op - } - function onlyChildT(child: Child) { - // no-op - } - function onlyChildSAndT(child: Child) { - // no-op - } - - if (obj instanceof Child) { - onlyChildS(obj); - ~~~ -!!! error TS2345: Argument of type 'Parent & Child' is not assignable to parameter of type 'Child'. -!!! error TS2345: Types of property 'value3' are incompatible. -!!! error TS2345: Type 'S | T' is not assignable to type 'S'. -!!! error TS2345: Type 'T' is not assignable to type 'S'. - onlyChildT(obj); - ~~~ -!!! error TS2345: Argument of type 'Parent & Child' is not assignable to parameter of type 'Child'. -!!! error TS2345: Types of property 'value3' are incompatible. -!!! error TS2345: Type 'S | T' is not assignable to type 'T'. -!!! error TS2345: Type 'S' is not assignable to type 'T'. - onlyChildSAndT(obj); - ~~~ -!!! error TS2345: Argument of type 'Parent & Child' is not assignable to parameter of type 'Child'. -!!! error TS2345: Types of property 'value3' are incompatible. -!!! error TS2345: Type 'S | T' is not assignable to type 'S & T'. -!!! error TS2345: Type 'S' is not assignable to type 'S & T'. -!!! error TS2345: Type 'S' is not assignable to type 'T'. - } - } - - function example6() { - class Parent { - value1: A; - value2: B; - } - - class Child extends Parent { - value3: C; - } - - const obj: - | Parent<{ foo: string }, { foo: string }> - | Parent - | Parent = undefined as any; - - const obj1 = undefined as Parent<{ foo: string }, { foo: string }>; - const obj2 = undefined as Parent; - const obj3 = undefined as Parent; - const obj4 = undefined as string | { foo: string }; - const obj5 = undefined as { foo: string }; - - function onlyChildString(child: Child) { - // no-op - } - function onlyChildNumber(child: Child) { - // no-op - } - - if (obj instanceof Child) { - onlyChildString(obj); - ~~~ -!!! error TS2345: Argument of type 'Child | Child | Child<{ foo: string; }>' is not assignable to parameter of type 'Child'. -!!! error TS2345: Type 'Child' is not assignable to type 'Child'. -!!! error TS2345: Type 'number' is not assignable to type 'string'. - onlyChildNumber(obj); - ~~~ -!!! error TS2345: Argument of type 'Child | Child | Child<{ foo: string; }>' is not assignable to parameter of type 'Child'. -!!! error TS2345: Type 'Child' is not assignable to type 'Child'. -!!! error TS2345: Type 'string' is not assignable to type 'number'. - } - - if (obj1 instanceof Child) { - console.log(obj1); - } - if (obj2 instanceof Child) { - console.log(obj2); - } - if (obj3 instanceof Child) { - console.log(obj3); - } - if (obj4 instanceof Child) { - console.log(obj4); - } - if (obj5 instanceof Child) { - console.log(obj5); - } - } - - function negative1() { - class Parent { - value1: A; - value2: B; - } - - class Child extends Parent { - value3: C; - } - - const obj: - | Parent - | Parent - | Child = undefined as any; - - if (obj instanceof Child) { - return; - } - - console.log(obj); - } - \ No newline at end of file diff --git a/tests/baselines/reference/narrowGenericTypeByInstanceOf.js b/tests/baselines/reference/narrowGenericTypeByInstanceOf.js index d1241defa49a5..4f09a8f64112b 100644 --- a/tests/baselines/reference/narrowGenericTypeByInstanceOf.js +++ b/tests/baselines/reference/narrowGenericTypeByInstanceOf.js @@ -1,7 +1,5 @@ //// [narrowGenericTypeByInstanceOf.ts] -import { stringify } from "querystring"; - -function example1() { +function exampleSingleArgument() { class Parent { value: T; } @@ -10,22 +8,13 @@ function example1() { other: T; } - const obj = new Parent(); - - function onlyChildNumber(child: Child) { - // no-op - } - function onlyChildString(child: Child) { - // no-op - } + const obj: Parent = undefined as any; if (obj instanceof Child) { - onlyChildNumber(obj); // should PASS - - onlyChildString(obj); // should ERROR: Child is not assignable to Child. + obj; } } -function example2() { +function exampleSingleExtendsMultiple() { class Parent { value1: A; value2: B; @@ -35,23 +24,14 @@ function example2() { other: T; } - const obj = new Parent(); - - function onlyChildNumber(child: Child) { - // no-op - } - function onlyChildString(child: Child) { - // no-op - } + const obj: Parent = undefined as any; if (obj instanceof Child) { - onlyChildNumber(obj); // should PASS - - onlyChildString(obj); // should ERROR: Child is not assignable to Child. + obj; } } -function example3() { +function exampleSwapParameterOrder() { class Parent { value1: A; value2: B; @@ -62,62 +42,14 @@ function example3() { value4: D; } - const obj = new Parent(); - - function onlyChildNumberString(child: Child) { - // no-op - } - function onlyChildStringNumber(child: Child) { - // no-op - } - function onlyChildNumberNumber(child: Child) { - // no-op - } + const obj: Parent = undefined as any; if (obj instanceof Child) { - onlyChildNumberString(obj); // should ERROR: Child is not assignable to Child. - onlyChildNumberNumber(obj); // should ERROR: Child is not assignable to Child. - - onlyChildStringNumber(obj); // should PASS - } -} - -function example4() { - class Parent { - value1: A; - value2: B; - } - - class Child extends Parent { - value3: C; - } - - const obj1 = new Parent(); - const obj2 = new Parent(); - - function onlyChildNumber(child: Child) { - // no-op - } - function onlyChildString(child: Child) { - // no-op - } - function onlyChildStringAndNumber(child: Child) { - // no-op - } - - if (obj1 instanceof Child) { - onlyChildNumber(obj1); - onlyChildString(obj1); - onlyChildStringAndNumber(obj1); - } - if (obj2 instanceof Child) { - onlyChildNumber(obj2); - onlyChildString(obj2); - onlyChildStringAndNumber(obj2); + obj; } } -function example5() { +function exampleSingleExtendsMultipleReject() { class Parent { value1: A; value2: B; @@ -127,26 +59,14 @@ function example5() { value3: C; } - const obj = new Parent(); - - function onlyChildS(child: Child) { - // no-op - } - function onlyChildT(child: Child) { - // no-op - } - function onlyChildSAndT(child: Child) { - // no-op - } + const obj: Parent = undefined as any; if (obj instanceof Child) { - onlyChildS(obj); - onlyChildT(obj); - onlyChildSAndT(obj); + obj; } } -function example6() { +function exampleUnion() { class Parent { value1: A; value2: B; @@ -156,47 +76,40 @@ function example6() { value3: C; } - const obj: + const obj0: | Parent<{ foo: string }, { foo: string }> | Parent | Parent = undefined as any; - - const obj1 = undefined as Parent<{ foo: string }, { foo: string }>; - const obj2 = undefined as Parent; - const obj3 = undefined as Parent; - const obj4 = undefined as string | { foo: string }; - const obj5 = undefined as { foo: string }; - - function onlyChildString(child: Child) { - // no-op - } - function onlyChildNumber(child: Child) { - // no-op - } - - if (obj instanceof Child) { - onlyChildString(obj); - onlyChildNumber(obj); + if (obj0 instanceof Child) { + obj0; } + const obj1 = undefined as Parent<{ foo: string }, { foo: string }>; if (obj1 instanceof Child) { - console.log(obj1); + obj1; } + + const obj2 = undefined as Parent; if (obj2 instanceof Child) { - console.log(obj2); + obj2; } + + const obj3 = undefined as Parent; if (obj3 instanceof Child) { - console.log(obj3); + obj3; } + + const obj4 = undefined as string | { foo: string }; if (obj4 instanceof Child) { - console.log(obj4); + obj4; } + const obj5 = undefined as { foo: string }; if (obj5 instanceof Child) { - console.log(obj5); + obj5; } } -function negative1() { +function exampleNegative() { class Parent { value1: A; value2: B; @@ -212,15 +125,56 @@ function negative1() { | Child = undefined as any; if (obj instanceof Child) { + // Here we filter out matching ones, instead of just narrowing to them. + obj; return; } console.log(obj); } + +function exampleIgnoreDefaults() { + // default parameters shouldn't have any impact on this narrowing. + class Parent { + a: A; + } + class Child extends Parent { + a2: A2; + c: C; + } + + const obj: Parent = undefined as any; + if (obj instanceof Child) { + obj; + } +} + +function exampleConstraints() { + class Parent { + a: A; + } + class Child extends Parent { + b: B; + } + + const objPass: Parent = undefined as any; + if (objPass instanceof Child) { + objPass; + } + + const objFour: Parent<4> = undefined as any; + if (objFour instanceof Child) { + objFour; + } + + const objFail: Parent = undefined as any; + if (objFail instanceof Child) { + objFail; + } +} //// [narrowGenericTypeByInstanceOf.js] -"use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || @@ -234,8 +188,7 @@ var __extends = (this && this.__extends) || (function () { d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); -exports.__esModule = true; -function example1() { +function exampleSingleArgument() { var Parent = /** @class */ (function () { function Parent() { } @@ -248,19 +201,12 @@ function example1() { } return Child; }(Parent)); - var obj = new Parent(); - function onlyChildNumber(child) { - // no-op - } - function onlyChildString(child) { - // no-op - } + var obj = undefined; if (obj instanceof Child) { - onlyChildNumber(obj); // should PASS - onlyChildString(obj); // should ERROR: Child is not assignable to Child. + obj; } } -function example2() { +function exampleSingleExtendsMultiple() { var Parent = /** @class */ (function () { function Parent() { } @@ -273,19 +219,12 @@ function example2() { } return Child; }(Parent)); - var obj = new Parent(); - function onlyChildNumber(child) { - // no-op - } - function onlyChildString(child) { - // no-op - } + var obj = undefined; if (obj instanceof Child) { - onlyChildNumber(obj); // should PASS - onlyChildString(obj); // should ERROR: Child is not assignable to Child. + obj; } } -function example3() { +function exampleSwapParameterOrder() { var Parent = /** @class */ (function () { function Parent() { } @@ -298,23 +237,12 @@ function example3() { } return Child; }(Parent)); - var obj = new Parent(); - function onlyChildNumberString(child) { - // no-op - } - function onlyChildStringNumber(child) { - // no-op - } - function onlyChildNumberNumber(child) { - // no-op - } + var obj = undefined; if (obj instanceof Child) { - onlyChildNumberString(obj); // should ERROR: Child is not assignable to Child. - onlyChildNumberNumber(obj); // should ERROR: Child is not assignable to Child. - onlyChildStringNumber(obj); // should PASS + obj; } } -function example4() { +function exampleSingleExtendsMultipleReject() { var Parent = /** @class */ (function () { function Parent() { } @@ -327,29 +255,50 @@ function example4() { } return Child; }(Parent)); - var obj1 = new Parent(); - var obj2 = new Parent(); - function onlyChildNumber(child) { - // no-op - } - function onlyChildString(child) { - // no-op + var obj = undefined; + if (obj instanceof Child) { + obj; } - function onlyChildStringAndNumber(child) { - // no-op +} +function exampleUnion() { + var Parent = /** @class */ (function () { + function Parent() { + } + return Parent; + }()); + var Child = /** @class */ (function (_super) { + __extends(Child, _super); + function Child() { + return _super !== null && _super.apply(this, arguments) || this; + } + return Child; + }(Parent)); + var obj0 = undefined; + if (obj0 instanceof Child) { + obj0; } + var obj1 = undefined; if (obj1 instanceof Child) { - onlyChildNumber(obj1); - onlyChildString(obj1); - onlyChildStringAndNumber(obj1); + obj1; } + var obj2 = undefined; if (obj2 instanceof Child) { - onlyChildNumber(obj2); - onlyChildString(obj2); - onlyChildStringAndNumber(obj2); + obj2; + } + var obj3 = undefined; + if (obj3 instanceof Child) { + obj3; + } + var obj4 = undefined; + if (obj4 instanceof Child) { + obj4; + } + var obj5 = undefined; + if (obj5 instanceof Child) { + obj5; } } -function example5() { +function exampleNegative() { var Parent = /** @class */ (function () { function Parent() { } @@ -362,23 +311,16 @@ function example5() { } return Child; }(Parent)); - var obj = new Parent(); - function onlyChildS(child) { - // no-op - } - function onlyChildT(child) { - // no-op - } - function onlyChildSAndT(child) { - // no-op - } + var obj = undefined; if (obj instanceof Child) { - onlyChildS(obj); - onlyChildT(obj); - onlyChildSAndT(obj); + // Here we filter out matching ones, instead of just narrowing to them. + obj; + return; } + console.log(obj); } -function example6() { +function exampleIgnoreDefaults() { + // default parameters shouldn't have any impact on this narrowing. var Parent = /** @class */ (function () { function Parent() { } @@ -392,38 +334,11 @@ function example6() { return Child; }(Parent)); var obj = undefined; - var obj1 = undefined; - var obj2 = undefined; - var obj3 = undefined; - var obj4 = undefined; - var obj5 = undefined; - function onlyChildString(child) { - // no-op - } - function onlyChildNumber(child) { - // no-op - } if (obj instanceof Child) { - onlyChildString(obj); - onlyChildNumber(obj); - } - if (obj1 instanceof Child) { - console.log(obj1); - } - if (obj2 instanceof Child) { - console.log(obj2); - } - if (obj3 instanceof Child) { - console.log(obj3); - } - if (obj4 instanceof Child) { - console.log(obj4); - } - if (obj5 instanceof Child) { - console.log(obj5); + obj; } } -function negative1() { +function exampleConstraints() { var Parent = /** @class */ (function () { function Parent() { } @@ -436,9 +351,16 @@ function negative1() { } return Child; }(Parent)); - var obj = undefined; - if (obj instanceof Child) { - return; + var objPass = undefined; + if (objPass instanceof Child) { + objPass; + } + var objFour = undefined; + if (objFour instanceof Child) { + objFour; + } + var objFail = undefined; + if (objFail instanceof Child) { + objFail; } - console.log(obj); } diff --git a/tests/baselines/reference/narrowGenericTypeByInstanceOf.symbols b/tests/baselines/reference/narrowGenericTypeByInstanceOf.symbols index d31ee4276e158..add6ed52ea1e4 100644 --- a/tests/baselines/reference/narrowGenericTypeByInstanceOf.symbols +++ b/tests/baselines/reference/narrowGenericTypeByInstanceOf.symbols @@ -1,580 +1,454 @@ === tests/cases/compiler/narrowGenericTypeByInstanceOf.ts === -import { stringify } from "querystring"; ->stringify : Symbol(stringify, Decl(narrowGenericTypeByInstanceOf.ts, 0, 8)) - -function example1() { ->example1 : Symbol(example1, Decl(narrowGenericTypeByInstanceOf.ts, 0, 40)) +function exampleSingleArgument() { +>exampleSingleArgument : Symbol(exampleSingleArgument, Decl(narrowGenericTypeByInstanceOf.ts, 0, 0)) class Parent { ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 2, 21)) ->T : Symbol(T, Decl(narrowGenericTypeByInstanceOf.ts, 3, 15)) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 0, 34)) +>T : Symbol(T, Decl(narrowGenericTypeByInstanceOf.ts, 1, 15)) value: T; ->value : Symbol(Parent.value, Decl(narrowGenericTypeByInstanceOf.ts, 3, 19)) ->T : Symbol(T, Decl(narrowGenericTypeByInstanceOf.ts, 3, 15)) +>value : Symbol(Parent.value, Decl(narrowGenericTypeByInstanceOf.ts, 1, 19)) +>T : Symbol(T, Decl(narrowGenericTypeByInstanceOf.ts, 1, 15)) } class Child extends Parent { ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 5, 3)) ->T : Symbol(T, Decl(narrowGenericTypeByInstanceOf.ts, 7, 14)) ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 2, 21)) ->T : Symbol(T, Decl(narrowGenericTypeByInstanceOf.ts, 7, 14)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 3, 3)) +>T : Symbol(T, Decl(narrowGenericTypeByInstanceOf.ts, 5, 14)) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 0, 34)) +>T : Symbol(T, Decl(narrowGenericTypeByInstanceOf.ts, 5, 14)) other: T; ->other : Symbol(Child.other, Decl(narrowGenericTypeByInstanceOf.ts, 7, 36)) ->T : Symbol(T, Decl(narrowGenericTypeByInstanceOf.ts, 7, 14)) - } - - const obj = new Parent(); ->obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 11, 7)) ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 2, 21)) - - function onlyChildNumber(child: Child) { ->onlyChildNumber : Symbol(onlyChildNumber, Decl(narrowGenericTypeByInstanceOf.ts, 11, 35)) ->child : Symbol(child, Decl(narrowGenericTypeByInstanceOf.ts, 13, 27)) ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 5, 3)) - - // no-op +>other : Symbol(Child.other, Decl(narrowGenericTypeByInstanceOf.ts, 5, 36)) +>T : Symbol(T, Decl(narrowGenericTypeByInstanceOf.ts, 5, 14)) } - function onlyChildString(child: Child) { ->onlyChildString : Symbol(onlyChildString, Decl(narrowGenericTypeByInstanceOf.ts, 15, 3)) ->child : Symbol(child, Decl(narrowGenericTypeByInstanceOf.ts, 16, 27)) ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 5, 3)) - // no-op - } + const obj: Parent = undefined as any; +>obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 9, 7)) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 0, 34)) +>undefined : Symbol(undefined) if (obj instanceof Child) { ->obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 11, 7)) ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 5, 3)) - - onlyChildNumber(obj); // should PASS ->onlyChildNumber : Symbol(onlyChildNumber, Decl(narrowGenericTypeByInstanceOf.ts, 11, 35)) ->obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 11, 7)) +>obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 9, 7)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 3, 3)) - onlyChildString(obj); // should ERROR: Child is not assignable to Child. ->onlyChildString : Symbol(onlyChildString, Decl(narrowGenericTypeByInstanceOf.ts, 15, 3)) ->obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 11, 7)) + obj; +>obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 9, 7)) } } -function example2() { ->example2 : Symbol(example2, Decl(narrowGenericTypeByInstanceOf.ts, 25, 1)) +function exampleSingleExtendsMultiple() { +>exampleSingleExtendsMultiple : Symbol(exampleSingleExtendsMultiple, Decl(narrowGenericTypeByInstanceOf.ts, 14, 1)) class Parent { ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 26, 21)) ->A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 27, 15)) ->B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 27, 17)) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 15, 41)) +>A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 16, 15)) +>B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 16, 17)) value1: A; ->value1 : Symbol(Parent.value1, Decl(narrowGenericTypeByInstanceOf.ts, 27, 22)) ->A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 27, 15)) +>value1 : Symbol(Parent.value1, Decl(narrowGenericTypeByInstanceOf.ts, 16, 22)) +>A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 16, 15)) value2: B; ->value2 : Symbol(Parent.value2, Decl(narrowGenericTypeByInstanceOf.ts, 28, 14)) ->B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 27, 17)) +>value2 : Symbol(Parent.value2, Decl(narrowGenericTypeByInstanceOf.ts, 17, 14)) +>B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 16, 17)) } class Child extends Parent { ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 30, 3)) ->T : Symbol(T, Decl(narrowGenericTypeByInstanceOf.ts, 32, 14)) ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 26, 21)) ->T : Symbol(T, Decl(narrowGenericTypeByInstanceOf.ts, 32, 14)) ->T : Symbol(T, Decl(narrowGenericTypeByInstanceOf.ts, 32, 14)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 19, 3)) +>T : Symbol(T, Decl(narrowGenericTypeByInstanceOf.ts, 21, 14)) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 15, 41)) +>T : Symbol(T, Decl(narrowGenericTypeByInstanceOf.ts, 21, 14)) +>T : Symbol(T, Decl(narrowGenericTypeByInstanceOf.ts, 21, 14)) other: T; ->other : Symbol(Child.other, Decl(narrowGenericTypeByInstanceOf.ts, 32, 39)) ->T : Symbol(T, Decl(narrowGenericTypeByInstanceOf.ts, 32, 14)) +>other : Symbol(Child.other, Decl(narrowGenericTypeByInstanceOf.ts, 21, 39)) +>T : Symbol(T, Decl(narrowGenericTypeByInstanceOf.ts, 21, 14)) } - const obj = new Parent(); ->obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 36, 7)) ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 26, 21)) - - function onlyChildNumber(child: Child) { ->onlyChildNumber : Symbol(onlyChildNumber, Decl(narrowGenericTypeByInstanceOf.ts, 36, 43)) ->child : Symbol(child, Decl(narrowGenericTypeByInstanceOf.ts, 38, 27)) ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 30, 3)) - - // no-op - } - function onlyChildString(child: Child) { ->onlyChildString : Symbol(onlyChildString, Decl(narrowGenericTypeByInstanceOf.ts, 40, 3)) ->child : Symbol(child, Decl(narrowGenericTypeByInstanceOf.ts, 41, 27)) ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 30, 3)) - - // no-op - } + const obj: Parent = undefined as any; +>obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 25, 7)) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 15, 41)) +>undefined : Symbol(undefined) if (obj instanceof Child) { ->obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 36, 7)) ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 30, 3)) - - onlyChildNumber(obj); // should PASS ->onlyChildNumber : Symbol(onlyChildNumber, Decl(narrowGenericTypeByInstanceOf.ts, 36, 43)) ->obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 36, 7)) +>obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 25, 7)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 19, 3)) - onlyChildString(obj); // should ERROR: Child is not assignable to Child. ->onlyChildString : Symbol(onlyChildString, Decl(narrowGenericTypeByInstanceOf.ts, 40, 3)) ->obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 36, 7)) + obj; +>obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 25, 7)) } } -function example3() { ->example3 : Symbol(example3, Decl(narrowGenericTypeByInstanceOf.ts, 50, 1)) +function exampleSwapParameterOrder() { +>exampleSwapParameterOrder : Symbol(exampleSwapParameterOrder, Decl(narrowGenericTypeByInstanceOf.ts, 30, 1)) class Parent { ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 52, 21)) ->A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 53, 15)) ->B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 53, 17)) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 32, 38)) +>A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 33, 15)) +>B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 33, 17)) value1: A; ->value1 : Symbol(Parent.value1, Decl(narrowGenericTypeByInstanceOf.ts, 53, 22)) ->A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 53, 15)) +>value1 : Symbol(Parent.value1, Decl(narrowGenericTypeByInstanceOf.ts, 33, 22)) +>A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 33, 15)) value2: B; ->value2 : Symbol(Parent.value2, Decl(narrowGenericTypeByInstanceOf.ts, 54, 14)) ->B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 53, 17)) +>value2 : Symbol(Parent.value2, Decl(narrowGenericTypeByInstanceOf.ts, 34, 14)) +>B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 33, 17)) } class Child extends Parent { ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 56, 3)) ->C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 58, 14)) ->D : Symbol(D, Decl(narrowGenericTypeByInstanceOf.ts, 58, 16)) ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 52, 21)) ->D : Symbol(D, Decl(narrowGenericTypeByInstanceOf.ts, 58, 16)) ->C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 58, 14)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 36, 3)) +>C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 38, 14)) +>D : Symbol(D, Decl(narrowGenericTypeByInstanceOf.ts, 38, 16)) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 32, 38)) +>D : Symbol(D, Decl(narrowGenericTypeByInstanceOf.ts, 38, 16)) +>C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 38, 14)) value3: C; ->value3 : Symbol(Child.value3, Decl(narrowGenericTypeByInstanceOf.ts, 58, 42)) ->C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 58, 14)) +>value3 : Symbol(Child.value3, Decl(narrowGenericTypeByInstanceOf.ts, 38, 42)) +>C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 38, 14)) value4: D; ->value4 : Symbol(Child.value4, Decl(narrowGenericTypeByInstanceOf.ts, 59, 14)) ->D : Symbol(D, Decl(narrowGenericTypeByInstanceOf.ts, 58, 16)) +>value4 : Symbol(Child.value4, Decl(narrowGenericTypeByInstanceOf.ts, 39, 14)) +>D : Symbol(D, Decl(narrowGenericTypeByInstanceOf.ts, 38, 16)) } - const obj = new Parent(); ->obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 63, 7)) ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 52, 21)) + const obj: Parent = undefined as any; +>obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 43, 7)) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 32, 38)) +>undefined : Symbol(undefined) - function onlyChildNumberString(child: Child) { ->onlyChildNumberString : Symbol(onlyChildNumberString, Decl(narrowGenericTypeByInstanceOf.ts, 63, 43)) ->child : Symbol(child, Decl(narrowGenericTypeByInstanceOf.ts, 65, 33)) ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 56, 3)) + if (obj instanceof Child) { +>obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 43, 7)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 36, 3)) - // no-op + obj; +>obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 43, 7)) } - function onlyChildStringNumber(child: Child) { ->onlyChildStringNumber : Symbol(onlyChildStringNumber, Decl(narrowGenericTypeByInstanceOf.ts, 67, 3)) ->child : Symbol(child, Decl(narrowGenericTypeByInstanceOf.ts, 68, 33)) ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 56, 3)) +} - // no-op - } - function onlyChildNumberNumber(child: Child) { ->onlyChildNumberNumber : Symbol(onlyChildNumberNumber, Decl(narrowGenericTypeByInstanceOf.ts, 70, 3)) ->child : Symbol(child, Decl(narrowGenericTypeByInstanceOf.ts, 71, 33)) ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 56, 3)) +function exampleSingleExtendsMultipleReject() { +>exampleSingleExtendsMultipleReject : Symbol(exampleSingleExtendsMultipleReject, Decl(narrowGenericTypeByInstanceOf.ts, 48, 1)) - // no-op + class Parent { +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 50, 47)) +>A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 51, 15)) +>B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 51, 17)) + + value1: A; +>value1 : Symbol(Parent.value1, Decl(narrowGenericTypeByInstanceOf.ts, 51, 22)) +>A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 51, 15)) + + value2: B; +>value2 : Symbol(Parent.value2, Decl(narrowGenericTypeByInstanceOf.ts, 52, 14)) +>B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 51, 17)) } - if (obj instanceof Child) { ->obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 63, 7)) ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 56, 3)) + class Child extends Parent { +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 54, 3)) +>C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 56, 14)) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 50, 47)) +>C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 56, 14)) +>C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 56, 14)) + + value3: C; +>value3 : Symbol(Child.value3, Decl(narrowGenericTypeByInstanceOf.ts, 56, 39)) +>C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 56, 14)) + } - onlyChildNumberString(obj); // should ERROR: Child is not assignable to Child. ->onlyChildNumberString : Symbol(onlyChildNumberString, Decl(narrowGenericTypeByInstanceOf.ts, 63, 43)) ->obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 63, 7)) + const obj: Parent = undefined as any; +>obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 60, 7)) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 50, 47)) +>undefined : Symbol(undefined) - onlyChildNumberNumber(obj); // should ERROR: Child is not assignable to Child. ->onlyChildNumberNumber : Symbol(onlyChildNumberNumber, Decl(narrowGenericTypeByInstanceOf.ts, 70, 3)) ->obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 63, 7)) + if (obj instanceof Child) { +>obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 60, 7)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 54, 3)) - onlyChildStringNumber(obj); // should PASS ->onlyChildStringNumber : Symbol(onlyChildStringNumber, Decl(narrowGenericTypeByInstanceOf.ts, 67, 3)) ->obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 63, 7)) + obj; +>obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 60, 7)) } } -function example4() { ->example4 : Symbol(example4, Decl(narrowGenericTypeByInstanceOf.ts, 81, 1)) +function exampleUnion() { +>exampleUnion : Symbol(exampleUnion, Decl(narrowGenericTypeByInstanceOf.ts, 65, 1)) class Parent { ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 83, 21)) ->A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 84, 15)) ->B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 84, 17)) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 67, 25)) +>A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 68, 15)) +>B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 68, 17)) value1: A; ->value1 : Symbol(Parent.value1, Decl(narrowGenericTypeByInstanceOf.ts, 84, 22)) ->A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 84, 15)) +>value1 : Symbol(Parent.value1, Decl(narrowGenericTypeByInstanceOf.ts, 68, 22)) +>A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 68, 15)) value2: B; ->value2 : Symbol(Parent.value2, Decl(narrowGenericTypeByInstanceOf.ts, 85, 14)) ->B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 84, 17)) +>value2 : Symbol(Parent.value2, Decl(narrowGenericTypeByInstanceOf.ts, 69, 14)) +>B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 68, 17)) } class Child extends Parent { ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 87, 3)) ->C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 89, 14)) ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 83, 21)) ->C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 89, 14)) ->C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 89, 14)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 71, 3)) +>C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 73, 14)) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 67, 25)) +>C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 73, 14)) +>C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 73, 14)) value3: C; ->value3 : Symbol(Child.value3, Decl(narrowGenericTypeByInstanceOf.ts, 89, 39)) ->C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 89, 14)) +>value3 : Symbol(Child.value3, Decl(narrowGenericTypeByInstanceOf.ts, 73, 39)) +>C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 73, 14)) } - const obj1 = new Parent(); ->obj1 : Symbol(obj1, Decl(narrowGenericTypeByInstanceOf.ts, 93, 7)) ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 83, 21)) + const obj0: +>obj0 : Symbol(obj0, Decl(narrowGenericTypeByInstanceOf.ts, 77, 7)) - const obj2 = new Parent(); ->obj2 : Symbol(obj2, Decl(narrowGenericTypeByInstanceOf.ts, 94, 7)) ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 83, 21)) + | Parent<{ foo: string }, { foo: string }> +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 67, 25)) +>foo : Symbol(foo, Decl(narrowGenericTypeByInstanceOf.ts, 78, 14)) +>foo : Symbol(foo, Decl(narrowGenericTypeByInstanceOf.ts, 78, 31)) - function onlyChildNumber(child: Child) { ->onlyChildNumber : Symbol(onlyChildNumber, Decl(narrowGenericTypeByInstanceOf.ts, 94, 44)) ->child : Symbol(child, Decl(narrowGenericTypeByInstanceOf.ts, 96, 27)) ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 87, 3)) + | Parent +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 67, 25)) - // no-op - } - function onlyChildString(child: Child) { ->onlyChildString : Symbol(onlyChildString, Decl(narrowGenericTypeByInstanceOf.ts, 98, 3)) ->child : Symbol(child, Decl(narrowGenericTypeByInstanceOf.ts, 99, 27)) ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 87, 3)) + | Parent = undefined as any; +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 67, 25)) +>undefined : Symbol(undefined) - // no-op - } - function onlyChildStringAndNumber(child: Child) { ->onlyChildStringAndNumber : Symbol(onlyChildStringAndNumber, Decl(narrowGenericTypeByInstanceOf.ts, 101, 3)) ->child : Symbol(child, Decl(narrowGenericTypeByInstanceOf.ts, 102, 36)) ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 87, 3)) + if (obj0 instanceof Child) { +>obj0 : Symbol(obj0, Decl(narrowGenericTypeByInstanceOf.ts, 77, 7)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 71, 3)) - // no-op + obj0; +>obj0 : Symbol(obj0, Decl(narrowGenericTypeByInstanceOf.ts, 77, 7)) } - if (obj1 instanceof Child) { ->obj1 : Symbol(obj1, Decl(narrowGenericTypeByInstanceOf.ts, 93, 7)) ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 87, 3)) - - onlyChildNumber(obj1); ->onlyChildNumber : Symbol(onlyChildNumber, Decl(narrowGenericTypeByInstanceOf.ts, 94, 44)) ->obj1 : Symbol(obj1, Decl(narrowGenericTypeByInstanceOf.ts, 93, 7)) + const obj1 = undefined as Parent<{ foo: string }, { foo: string }>; +>obj1 : Symbol(obj1, Decl(narrowGenericTypeByInstanceOf.ts, 85, 7)) +>undefined : Symbol(undefined) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 67, 25)) +>foo : Symbol(foo, Decl(narrowGenericTypeByInstanceOf.ts, 85, 36)) +>foo : Symbol(foo, Decl(narrowGenericTypeByInstanceOf.ts, 85, 53)) - onlyChildString(obj1); ->onlyChildString : Symbol(onlyChildString, Decl(narrowGenericTypeByInstanceOf.ts, 98, 3)) ->obj1 : Symbol(obj1, Decl(narrowGenericTypeByInstanceOf.ts, 93, 7)) + if (obj1 instanceof Child) { +>obj1 : Symbol(obj1, Decl(narrowGenericTypeByInstanceOf.ts, 85, 7)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 71, 3)) - onlyChildStringAndNumber(obj1); ->onlyChildStringAndNumber : Symbol(onlyChildStringAndNumber, Decl(narrowGenericTypeByInstanceOf.ts, 101, 3)) ->obj1 : Symbol(obj1, Decl(narrowGenericTypeByInstanceOf.ts, 93, 7)) + obj1; +>obj1 : Symbol(obj1, Decl(narrowGenericTypeByInstanceOf.ts, 85, 7)) } - if (obj2 instanceof Child) { ->obj2 : Symbol(obj2, Decl(narrowGenericTypeByInstanceOf.ts, 94, 7)) ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 87, 3)) - onlyChildNumber(obj2); ->onlyChildNumber : Symbol(onlyChildNumber, Decl(narrowGenericTypeByInstanceOf.ts, 94, 44)) ->obj2 : Symbol(obj2, Decl(narrowGenericTypeByInstanceOf.ts, 94, 7)) + const obj2 = undefined as Parent; +>obj2 : Symbol(obj2, Decl(narrowGenericTypeByInstanceOf.ts, 90, 7)) +>undefined : Symbol(undefined) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 67, 25)) - onlyChildString(obj2); ->onlyChildString : Symbol(onlyChildString, Decl(narrowGenericTypeByInstanceOf.ts, 98, 3)) ->obj2 : Symbol(obj2, Decl(narrowGenericTypeByInstanceOf.ts, 94, 7)) + if (obj2 instanceof Child) { +>obj2 : Symbol(obj2, Decl(narrowGenericTypeByInstanceOf.ts, 90, 7)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 71, 3)) - onlyChildStringAndNumber(obj2); ->onlyChildStringAndNumber : Symbol(onlyChildStringAndNumber, Decl(narrowGenericTypeByInstanceOf.ts, 101, 3)) ->obj2 : Symbol(obj2, Decl(narrowGenericTypeByInstanceOf.ts, 94, 7)) + obj2; +>obj2 : Symbol(obj2, Decl(narrowGenericTypeByInstanceOf.ts, 90, 7)) } -} - -function example5() { ->example5 : Symbol(example5, Decl(narrowGenericTypeByInstanceOf.ts, 116, 1)) ->S : Symbol(S, Decl(narrowGenericTypeByInstanceOf.ts, 118, 18)) ->T : Symbol(T, Decl(narrowGenericTypeByInstanceOf.ts, 118, 20)) - class Parent { ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 118, 27)) ->A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 119, 15)) ->B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 119, 17)) - - value1: A; ->value1 : Symbol(Parent.value1, Decl(narrowGenericTypeByInstanceOf.ts, 119, 22)) ->A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 119, 15)) - - value2: B; ->value2 : Symbol(Parent.value2, Decl(narrowGenericTypeByInstanceOf.ts, 120, 14)) ->B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 119, 17)) - } + const obj3 = undefined as Parent; +>obj3 : Symbol(obj3, Decl(narrowGenericTypeByInstanceOf.ts, 95, 7)) +>undefined : Symbol(undefined) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 67, 25)) - class Child extends Parent { ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 122, 3)) ->C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 124, 14)) ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 118, 27)) ->C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 124, 14)) ->C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 124, 14)) + if (obj3 instanceof Child) { +>obj3 : Symbol(obj3, Decl(narrowGenericTypeByInstanceOf.ts, 95, 7)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 71, 3)) - value3: C; ->value3 : Symbol(Child.value3, Decl(narrowGenericTypeByInstanceOf.ts, 124, 39)) ->C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 124, 14)) + obj3; +>obj3 : Symbol(obj3, Decl(narrowGenericTypeByInstanceOf.ts, 95, 7)) } - const obj = new Parent(); ->obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 128, 7)) ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 118, 27)) ->S : Symbol(S, Decl(narrowGenericTypeByInstanceOf.ts, 118, 18)) ->T : Symbol(T, Decl(narrowGenericTypeByInstanceOf.ts, 118, 20)) - - function onlyChildS(child: Child) { ->onlyChildS : Symbol(onlyChildS, Decl(narrowGenericTypeByInstanceOf.ts, 128, 33)) ->child : Symbol(child, Decl(narrowGenericTypeByInstanceOf.ts, 130, 22)) ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 122, 3)) ->S : Symbol(S, Decl(narrowGenericTypeByInstanceOf.ts, 118, 18)) + const obj4 = undefined as string | { foo: string }; +>obj4 : Symbol(obj4, Decl(narrowGenericTypeByInstanceOf.ts, 100, 7)) +>undefined : Symbol(undefined) +>foo : Symbol(foo, Decl(narrowGenericTypeByInstanceOf.ts, 100, 38)) - // no-op - } - function onlyChildT(child: Child) { ->onlyChildT : Symbol(onlyChildT, Decl(narrowGenericTypeByInstanceOf.ts, 132, 3)) ->child : Symbol(child, Decl(narrowGenericTypeByInstanceOf.ts, 133, 22)) ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 122, 3)) ->T : Symbol(T, Decl(narrowGenericTypeByInstanceOf.ts, 118, 20)) + if (obj4 instanceof Child) { +>obj4 : Symbol(obj4, Decl(narrowGenericTypeByInstanceOf.ts, 100, 7)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 71, 3)) - // no-op + obj4; +>obj4 : Symbol(obj4, Decl(narrowGenericTypeByInstanceOf.ts, 100, 7)) } - function onlyChildSAndT(child: Child) { ->onlyChildSAndT : Symbol(onlyChildSAndT, Decl(narrowGenericTypeByInstanceOf.ts, 135, 3)) ->child : Symbol(child, Decl(narrowGenericTypeByInstanceOf.ts, 136, 26)) ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 122, 3)) ->S : Symbol(S, Decl(narrowGenericTypeByInstanceOf.ts, 118, 18)) ->T : Symbol(T, Decl(narrowGenericTypeByInstanceOf.ts, 118, 20)) - - // no-op - } - - if (obj instanceof Child) { ->obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 128, 7)) ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 122, 3)) - - onlyChildS(obj); ->onlyChildS : Symbol(onlyChildS, Decl(narrowGenericTypeByInstanceOf.ts, 128, 33)) ->obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 128, 7)) + const obj5 = undefined as { foo: string }; +>obj5 : Symbol(obj5, Decl(narrowGenericTypeByInstanceOf.ts, 104, 7)) +>undefined : Symbol(undefined) +>foo : Symbol(foo, Decl(narrowGenericTypeByInstanceOf.ts, 104, 29)) - onlyChildT(obj); ->onlyChildT : Symbol(onlyChildT, Decl(narrowGenericTypeByInstanceOf.ts, 132, 3)) ->obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 128, 7)) + if (obj5 instanceof Child) { +>obj5 : Symbol(obj5, Decl(narrowGenericTypeByInstanceOf.ts, 104, 7)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 71, 3)) - onlyChildSAndT(obj); ->onlyChildSAndT : Symbol(onlyChildSAndT, Decl(narrowGenericTypeByInstanceOf.ts, 135, 3)) ->obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 128, 7)) + obj5; +>obj5 : Symbol(obj5, Decl(narrowGenericTypeByInstanceOf.ts, 104, 7)) } } -function example6() { ->example6 : Symbol(example6, Decl(narrowGenericTypeByInstanceOf.ts, 145, 1)) +function exampleNegative() { +>exampleNegative : Symbol(exampleNegative, Decl(narrowGenericTypeByInstanceOf.ts, 108, 1)) class Parent { ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 147, 21)) ->A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 148, 15)) ->B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 148, 17)) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 110, 28)) +>A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 111, 15)) +>B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 111, 17)) value1: A; ->value1 : Symbol(Parent.value1, Decl(narrowGenericTypeByInstanceOf.ts, 148, 22)) ->A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 148, 15)) +>value1 : Symbol(Parent.value1, Decl(narrowGenericTypeByInstanceOf.ts, 111, 22)) +>A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 111, 15)) value2: B; ->value2 : Symbol(Parent.value2, Decl(narrowGenericTypeByInstanceOf.ts, 149, 14)) ->B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 148, 17)) +>value2 : Symbol(Parent.value2, Decl(narrowGenericTypeByInstanceOf.ts, 112, 14)) +>B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 111, 17)) } class Child extends Parent { ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 151, 3)) ->C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 153, 14)) ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 147, 21)) ->C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 153, 14)) ->C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 153, 14)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 114, 3)) +>C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 116, 14)) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 110, 28)) +>C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 116, 14)) +>C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 116, 14)) value3: C; ->value3 : Symbol(Child.value3, Decl(narrowGenericTypeByInstanceOf.ts, 153, 39)) ->C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 153, 14)) +>value3 : Symbol(Child.value3, Decl(narrowGenericTypeByInstanceOf.ts, 116, 39)) +>C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 116, 14)) } const obj: ->obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 157, 7)) - - | Parent<{ foo: string }, { foo: string }> ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 147, 21)) ->foo : Symbol(foo, Decl(narrowGenericTypeByInstanceOf.ts, 158, 14)) ->foo : Symbol(foo, Decl(narrowGenericTypeByInstanceOf.ts, 158, 31)) +>obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 120, 7)) | Parent ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 147, 21)) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 110, 28)) - | Parent = undefined as any; ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 147, 21)) ->undefined : Symbol(undefined) - - const obj1 = undefined as Parent<{ foo: string }, { foo: string }>; ->obj1 : Symbol(obj1, Decl(narrowGenericTypeByInstanceOf.ts, 162, 7)) ->undefined : Symbol(undefined) ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 147, 21)) ->foo : Symbol(foo, Decl(narrowGenericTypeByInstanceOf.ts, 162, 36)) ->foo : Symbol(foo, Decl(narrowGenericTypeByInstanceOf.ts, 162, 53)) - - const obj2 = undefined as Parent; ->obj2 : Symbol(obj2, Decl(narrowGenericTypeByInstanceOf.ts, 163, 7)) ->undefined : Symbol(undefined) ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 147, 21)) - - const obj3 = undefined as Parent; ->obj3 : Symbol(obj3, Decl(narrowGenericTypeByInstanceOf.ts, 164, 7)) ->undefined : Symbol(undefined) ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 147, 21)) - - const obj4 = undefined as string | { foo: string }; ->obj4 : Symbol(obj4, Decl(narrowGenericTypeByInstanceOf.ts, 165, 7)) ->undefined : Symbol(undefined) ->foo : Symbol(foo, Decl(narrowGenericTypeByInstanceOf.ts, 165, 38)) + | Parent +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 110, 28)) - const obj5 = undefined as { foo: string }; ->obj5 : Symbol(obj5, Decl(narrowGenericTypeByInstanceOf.ts, 166, 7)) + | Child = undefined as any; +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 114, 3)) >undefined : Symbol(undefined) ->foo : Symbol(foo, Decl(narrowGenericTypeByInstanceOf.ts, 166, 29)) - - function onlyChildString(child: Child) { ->onlyChildString : Symbol(onlyChildString, Decl(narrowGenericTypeByInstanceOf.ts, 166, 44)) ->child : Symbol(child, Decl(narrowGenericTypeByInstanceOf.ts, 168, 27)) ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 151, 3)) - - // no-op - } - function onlyChildNumber(child: Child) { ->onlyChildNumber : Symbol(onlyChildNumber, Decl(narrowGenericTypeByInstanceOf.ts, 170, 3)) ->child : Symbol(child, Decl(narrowGenericTypeByInstanceOf.ts, 171, 27)) ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 151, 3)) - - // no-op - } if (obj instanceof Child) { ->obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 157, 7)) ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 151, 3)) +>obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 120, 7)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 114, 3)) - onlyChildString(obj); ->onlyChildString : Symbol(onlyChildString, Decl(narrowGenericTypeByInstanceOf.ts, 166, 44)) ->obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 157, 7)) + // Here we filter out matching ones, instead of just narrowing to them. + obj; +>obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 120, 7)) - onlyChildNumber(obj); ->onlyChildNumber : Symbol(onlyChildNumber, Decl(narrowGenericTypeByInstanceOf.ts, 170, 3)) ->obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 157, 7)) + return; } - if (obj1 instanceof Child) { ->obj1 : Symbol(obj1, Decl(narrowGenericTypeByInstanceOf.ts, 162, 7)) ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 151, 3)) - - console.log(obj1); + console.log(obj); >console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) >console : Symbol(console, Decl(lib.dom.d.ts, --, --)) >log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) ->obj1 : Symbol(obj1, Decl(narrowGenericTypeByInstanceOf.ts, 162, 7)) - } - if (obj2 instanceof Child) { ->obj2 : Symbol(obj2, Decl(narrowGenericTypeByInstanceOf.ts, 163, 7)) ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 151, 3)) +>obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 120, 7)) +} - console.log(obj2); ->console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) ->console : Symbol(console, Decl(lib.dom.d.ts, --, --)) ->log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) ->obj2 : Symbol(obj2, Decl(narrowGenericTypeByInstanceOf.ts, 163, 7)) - } - if (obj3 instanceof Child) { ->obj3 : Symbol(obj3, Decl(narrowGenericTypeByInstanceOf.ts, 164, 7)) ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 151, 3)) +function exampleIgnoreDefaults() { +>exampleIgnoreDefaults : Symbol(exampleIgnoreDefaults, Decl(narrowGenericTypeByInstanceOf.ts, 132, 1)) - console.log(obj3); ->console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) ->console : Symbol(console, Decl(lib.dom.d.ts, --, --)) ->log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) ->obj3 : Symbol(obj3, Decl(narrowGenericTypeByInstanceOf.ts, 164, 7)) + // default parameters shouldn't have any impact on this narrowing. + class Parent { +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 134, 34)) +>A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 136, 15)) + + a: A; +>a : Symbol(Parent.a, Decl(narrowGenericTypeByInstanceOf.ts, 136, 19)) +>A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 136, 15)) } - if (obj4 instanceof Child) { ->obj4 : Symbol(obj4, Decl(narrowGenericTypeByInstanceOf.ts, 165, 7)) ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 151, 3)) + class Child extends Parent { +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 138, 3)) +>A2 : Symbol(A2, Decl(narrowGenericTypeByInstanceOf.ts, 139, 14)) +>C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 139, 17)) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 134, 34)) +>A2 : Symbol(A2, Decl(narrowGenericTypeByInstanceOf.ts, 139, 14)) - console.log(obj4); ->console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) ->console : Symbol(console, Decl(lib.dom.d.ts, --, --)) ->log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) ->obj4 : Symbol(obj4, Decl(narrowGenericTypeByInstanceOf.ts, 165, 7)) + a2: A2; +>a2 : Symbol(Child.a2, Decl(narrowGenericTypeByInstanceOf.ts, 139, 50)) +>A2 : Symbol(A2, Decl(narrowGenericTypeByInstanceOf.ts, 139, 14)) + + c: C; +>c : Symbol(Child.c, Decl(narrowGenericTypeByInstanceOf.ts, 140, 11)) +>C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 139, 17)) } - if (obj5 instanceof Child) { ->obj5 : Symbol(obj5, Decl(narrowGenericTypeByInstanceOf.ts, 166, 7)) ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 151, 3)) - console.log(obj5); ->console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) ->console : Symbol(console, Decl(lib.dom.d.ts, --, --)) ->log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) ->obj5 : Symbol(obj5, Decl(narrowGenericTypeByInstanceOf.ts, 166, 7)) + const obj: Parent = undefined as any; +>obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 144, 7)) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 134, 34)) +>undefined : Symbol(undefined) + + if (obj instanceof Child) { +>obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 144, 7)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 138, 3)) + + obj; +>obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 144, 7)) } } -function negative1() { ->negative1 : Symbol(negative1, Decl(narrowGenericTypeByInstanceOf.ts, 195, 1)) +function exampleConstraints() { +>exampleConstraints : Symbol(exampleConstraints, Decl(narrowGenericTypeByInstanceOf.ts, 148, 1)) - class Parent { ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 197, 22)) ->A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 198, 15)) ->B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 198, 17)) + class Parent { +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 150, 31)) +>A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 151, 15)) - value1: A; ->value1 : Symbol(Parent.value1, Decl(narrowGenericTypeByInstanceOf.ts, 198, 22)) ->A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 198, 15)) + a: A; +>a : Symbol(Parent.a, Decl(narrowGenericTypeByInstanceOf.ts, 151, 19)) +>A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 151, 15)) + } + class Child extends Parent { +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 153, 3)) +>B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 154, 14)) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 150, 31)) +>B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 154, 14)) - value2: B; ->value2 : Symbol(Parent.value2, Decl(narrowGenericTypeByInstanceOf.ts, 199, 14)) ->B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 198, 17)) + b: B; +>b : Symbol(Child.b, Decl(narrowGenericTypeByInstanceOf.ts, 154, 51)) +>B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 154, 14)) } - class Child extends Parent { ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 201, 3)) ->C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 203, 14)) ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 197, 22)) ->C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 203, 14)) ->C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 203, 14)) + const objPass: Parent = undefined as any; +>objPass : Symbol(objPass, Decl(narrowGenericTypeByInstanceOf.ts, 158, 7)) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 150, 31)) +>undefined : Symbol(undefined) - value3: C; ->value3 : Symbol(Child.value3, Decl(narrowGenericTypeByInstanceOf.ts, 203, 39)) ->C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 203, 14)) + if (objPass instanceof Child) { +>objPass : Symbol(objPass, Decl(narrowGenericTypeByInstanceOf.ts, 158, 7)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 153, 3)) + + objPass; +>objPass : Symbol(objPass, Decl(narrowGenericTypeByInstanceOf.ts, 158, 7)) } - const obj: ->obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 207, 7)) + const objFour: Parent<4> = undefined as any; +>objFour : Symbol(objFour, Decl(narrowGenericTypeByInstanceOf.ts, 163, 7)) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 150, 31)) +>undefined : Symbol(undefined) - | Parent ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 197, 22)) + if (objFour instanceof Child) { +>objFour : Symbol(objFour, Decl(narrowGenericTypeByInstanceOf.ts, 163, 7)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 153, 3)) - | Parent ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 197, 22)) + objFour; +>objFour : Symbol(objFour, Decl(narrowGenericTypeByInstanceOf.ts, 163, 7)) + } - | Child = undefined as any; ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 201, 3)) + const objFail: Parent = undefined as any; +>objFail : Symbol(objFail, Decl(narrowGenericTypeByInstanceOf.ts, 168, 7)) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 150, 31)) >undefined : Symbol(undefined) - if (obj instanceof Child) { ->obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 207, 7)) ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 201, 3)) + if (objFail instanceof Child) { +>objFail : Symbol(objFail, Decl(narrowGenericTypeByInstanceOf.ts, 168, 7)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 153, 3)) - return; + objFail; +>objFail : Symbol(objFail, Decl(narrowGenericTypeByInstanceOf.ts, 168, 7)) } - - console.log(obj); ->console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) ->console : Symbol(console, Decl(lib.dom.d.ts, --, --)) ->log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) ->obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 207, 7)) } diff --git a/tests/baselines/reference/narrowGenericTypeByInstanceOf.types b/tests/baselines/reference/narrowGenericTypeByInstanceOf.types index 419b2c7254e3c..31bb3c4b75e01 100644 --- a/tests/baselines/reference/narrowGenericTypeByInstanceOf.types +++ b/tests/baselines/reference/narrowGenericTypeByInstanceOf.types @@ -1,9 +1,6 @@ === tests/cases/compiler/narrowGenericTypeByInstanceOf.ts === -import { stringify } from "querystring"; ->stringify : any - -function example1() { ->example1 : () => void +function exampleSingleArgument() { +>exampleSingleArgument : () => void class Parent { >Parent : Parent @@ -20,42 +17,22 @@ function example1() { >other : T } - const obj = new Parent(); + const obj: Parent = undefined as any; >obj : Parent ->new Parent() : Parent ->Parent : typeof Parent - - function onlyChildNumber(child: Child) { ->onlyChildNumber : (child: Child) => void ->child : Child - - // no-op - } - function onlyChildString(child: Child) { ->onlyChildString : (child: Child) => void ->child : Child - - // no-op - } +>undefined as any : any +>undefined : undefined if (obj instanceof Child) { >obj instanceof Child : boolean >obj : Parent >Child : typeof Child - onlyChildNumber(obj); // should PASS ->onlyChildNumber(obj) : void ->onlyChildNumber : (child: Child) => void ->obj : Child - - onlyChildString(obj); // should ERROR: Child is not assignable to Child. ->onlyChildString(obj) : void ->onlyChildString : (child: Child) => void + obj; >obj : Child } } -function example2() { ->example2 : () => void +function exampleSingleExtendsMultiple() { +>exampleSingleExtendsMultiple : () => void class Parent { >Parent : Parent @@ -75,43 +52,23 @@ function example2() { >other : T } - const obj = new Parent(); + const obj: Parent = undefined as any; >obj : Parent ->new Parent() : Parent ->Parent : typeof Parent - - function onlyChildNumber(child: Child) { ->onlyChildNumber : (child: Child) => void ->child : Child - - // no-op - } - function onlyChildString(child: Child) { ->onlyChildString : (child: Child) => void ->child : Child - - // no-op - } +>undefined as any : any +>undefined : undefined if (obj instanceof Child) { >obj instanceof Child : boolean >obj : Parent >Child : typeof Child - onlyChildNumber(obj); // should PASS ->onlyChildNumber(obj) : void ->onlyChildNumber : (child: Child) => void ->obj : Child - - onlyChildString(obj); // should ERROR: Child is not assignable to Child. ->onlyChildString(obj) : void ->onlyChildString : (child: Child) => void + obj; >obj : Child } } -function example3() { ->example3 : () => void +function exampleSwapParameterOrder() { +>exampleSwapParameterOrder : () => void class Parent { >Parent : Parent @@ -134,146 +91,23 @@ function example3() { >value4 : D } - const obj = new Parent(); + const obj: Parent = undefined as any; >obj : Parent ->new Parent() : Parent ->Parent : typeof Parent - - function onlyChildNumberString(child: Child) { ->onlyChildNumberString : (child: Child) => void ->child : Child - - // no-op - } - function onlyChildStringNumber(child: Child) { ->onlyChildStringNumber : (child: Child) => void ->child : Child - - // no-op - } - function onlyChildNumberNumber(child: Child) { ->onlyChildNumberNumber : (child: Child) => void ->child : Child - - // no-op - } +>undefined as any : any +>undefined : undefined if (obj instanceof Child) { >obj instanceof Child : boolean >obj : Parent >Child : typeof Child - onlyChildNumberString(obj); // should ERROR: Child is not assignable to Child. ->onlyChildNumberString(obj) : void ->onlyChildNumberString : (child: Child) => void ->obj : Child - - onlyChildNumberNumber(obj); // should ERROR: Child is not assignable to Child. ->onlyChildNumberNumber(obj) : void ->onlyChildNumberNumber : (child: Child) => void + obj; >obj : Child - - onlyChildStringNumber(obj); // should PASS ->onlyChildStringNumber(obj) : void ->onlyChildStringNumber : (child: Child) => void ->obj : Child - } -} - -function example4() { ->example4 : () => void - - class Parent { ->Parent : Parent - - value1: A; ->value1 : A - - value2: B; ->value2 : B - } - - class Child extends Parent { ->Child : Child ->Parent : Parent - - value3: C; ->value3 : C - } - - const obj1 = new Parent(); ->obj1 : Parent ->new Parent() : Parent ->Parent : typeof Parent - - const obj2 = new Parent(); ->obj2 : Parent ->new Parent() : Parent ->Parent : typeof Parent - - function onlyChildNumber(child: Child) { ->onlyChildNumber : (child: Child) => void ->child : Child - - // no-op - } - function onlyChildString(child: Child) { ->onlyChildString : (child: Child) => void ->child : Child - - // no-op - } - function onlyChildStringAndNumber(child: Child) { ->onlyChildStringAndNumber : (child: Child) => void ->child : Child - - // no-op - } - - if (obj1 instanceof Child) { ->obj1 instanceof Child : boolean ->obj1 : Parent ->Child : typeof Child - - onlyChildNumber(obj1); ->onlyChildNumber(obj1) : void ->onlyChildNumber : (child: Child) => void ->obj1 : Parent & Child - - onlyChildString(obj1); ->onlyChildString(obj1) : void ->onlyChildString : (child: Child) => void ->obj1 : Parent & Child - - onlyChildStringAndNumber(obj1); ->onlyChildStringAndNumber(obj1) : void ->onlyChildStringAndNumber : (child: Child) => void ->obj1 : Parent & Child - } - if (obj2 instanceof Child) { ->obj2 instanceof Child : boolean ->obj2 : Parent ->Child : typeof Child - - onlyChildNumber(obj2); ->onlyChildNumber(obj2) : void ->onlyChildNumber : (child: Child) => void ->obj2 : Child - - onlyChildString(obj2); ->onlyChildString(obj2) : void ->onlyChildString : (child: Child) => void ->obj2 : Child - - onlyChildStringAndNumber(obj2); ->onlyChildStringAndNumber(obj2) : void ->onlyChildStringAndNumber : (child: Child) => void ->obj2 : Child } } -function example5() { ->example5 : () => void +function exampleSingleExtendsMultipleReject() { +>exampleSingleExtendsMultipleReject : () => void class Parent { >Parent : Parent @@ -293,54 +127,23 @@ function example5() { >value3 : C } - const obj = new Parent(); ->obj : Parent ->new Parent() : Parent ->Parent : typeof Parent - - function onlyChildS(child: Child) { ->onlyChildS : (child: Child) => void ->child : Child - - // no-op - } - function onlyChildT(child: Child) { ->onlyChildT : (child: Child) => void ->child : Child - - // no-op - } - function onlyChildSAndT(child: Child) { ->onlyChildSAndT : (child: Child) => void ->child : Child - - // no-op - } + const obj: Parent = undefined as any; +>obj : Parent +>undefined as any : any +>undefined : undefined if (obj instanceof Child) { >obj instanceof Child : boolean ->obj : Parent +>obj : Parent >Child : typeof Child - onlyChildS(obj); ->onlyChildS(obj) : void ->onlyChildS : (child: Child) => void ->obj : Parent & Child - - onlyChildT(obj); ->onlyChildT(obj) : void ->onlyChildT : (child: Child) => void ->obj : Parent & Child - - onlyChildSAndT(obj); ->onlyChildSAndT(obj) : void ->onlyChildSAndT : (child: Child) => void ->obj : Parent & Child + obj; +>obj : Child } } -function example6() { ->example6 : () => void +function exampleUnion() { +>exampleUnion : () => void class Parent { >Parent : Parent @@ -360,8 +163,8 @@ function example6() { >value3 : C } - const obj: ->obj : Parent<{ foo: string; }, { foo: string; }> | Parent | Parent + const obj0: +>obj0 : Parent<{ foo: string; }, { foo: string; }> | Parent | Parent | Parent<{ foo: string }, { foo: string }> >foo : string @@ -372,6 +175,15 @@ function example6() { >undefined as any : any >undefined : undefined + if (obj0 instanceof Child) { +>obj0 instanceof Child : boolean +>obj0 : Parent<{ foo: string; }, { foo: string; }> | Parent | Parent +>Child : typeof Child + + obj0; +>obj0 : Child<{ foo: string; }> | Child | Child + } + const obj1 = undefined as Parent<{ foo: string }, { foo: string }>; >obj1 : Parent<{ foo: string; }, { foo: string; }> >undefined as Parent<{ foo: string }, { foo: string }> : Parent<{ foo: string; }, { foo: string; }> @@ -379,121 +191,75 @@ function example6() { >foo : string >foo : string - const obj2 = undefined as Parent; ->obj2 : Parent ->undefined as Parent : Parent ->undefined : undefined - - const obj3 = undefined as Parent; ->obj3 : Parent ->undefined as Parent : Parent ->undefined : undefined - - const obj4 = undefined as string | { foo: string }; ->obj4 : string | { foo: string; } ->undefined as string | { foo: string } : string | { foo: string; } ->undefined : undefined ->foo : string - - const obj5 = undefined as { foo: string }; ->obj5 : { foo: string; } ->undefined as { foo: string } : { foo: string; } ->undefined : undefined ->foo : string - - function onlyChildString(child: Child) { ->onlyChildString : (child: Child) => void ->child : Child - - // no-op - } - function onlyChildNumber(child: Child) { ->onlyChildNumber : (child: Child) => void ->child : Child - - // no-op - } - - if (obj instanceof Child) { ->obj instanceof Child : boolean ->obj : Parent<{ foo: string; }, { foo: string; }> | Parent | Parent ->Child : typeof Child - - onlyChildString(obj); ->onlyChildString(obj) : void ->onlyChildString : (child: Child) => void ->obj : Child | Child | Child<{ foo: string; }> - - onlyChildNumber(obj); ->onlyChildNumber(obj) : void ->onlyChildNumber : (child: Child) => void ->obj : Child | Child | Child<{ foo: string; }> - } - if (obj1 instanceof Child) { >obj1 instanceof Child : boolean >obj1 : Parent<{ foo: string; }, { foo: string; }> >Child : typeof Child - console.log(obj1); ->console.log(obj1) : void ->console.log : (message?: any, ...optionalParams: any[]) => void ->console : Console ->log : (message?: any, ...optionalParams: any[]) => void + obj1; >obj1 : Child<{ foo: string; }> } + + const obj2 = undefined as Parent; +>obj2 : Parent +>undefined as Parent : Parent +>undefined : undefined + if (obj2 instanceof Child) { >obj2 instanceof Child : boolean >obj2 : Parent >Child : typeof Child - console.log(obj2); ->console.log(obj2) : void ->console.log : (message?: any, ...optionalParams: any[]) => void ->console : Console ->log : (message?: any, ...optionalParams: any[]) => void + obj2; >obj2 : Child } + + const obj3 = undefined as Parent; +>obj3 : Parent +>undefined as Parent : Parent +>undefined : undefined + if (obj3 instanceof Child) { >obj3 instanceof Child : boolean >obj3 : Parent >Child : typeof Child - console.log(obj3); ->console.log(obj3) : void ->console.log : (message?: any, ...optionalParams: any[]) => void ->console : Console ->log : (message?: any, ...optionalParams: any[]) => void + obj3; >obj3 : Child } + + const obj4 = undefined as string | { foo: string }; +>obj4 : string | { foo: string; } +>undefined as string | { foo: string } : string | { foo: string; } +>undefined : undefined +>foo : string + if (obj4 instanceof Child) { >obj4 instanceof Child : boolean >obj4 : string | { foo: string; } >Child : typeof Child - console.log(obj4); ->console.log(obj4) : void ->console.log : (message?: any, ...optionalParams: any[]) => void ->console : Console ->log : (message?: any, ...optionalParams: any[]) => void + obj4; >obj4 : (string & Child) | ({ foo: string; } & Child) } + const obj5 = undefined as { foo: string }; +>obj5 : { foo: string; } +>undefined as { foo: string } : { foo: string; } +>undefined : undefined +>foo : string + if (obj5 instanceof Child) { >obj5 instanceof Child : boolean >obj5 : { foo: string; } >Child : typeof Child - console.log(obj5); ->console.log(obj5) : void ->console.log : (message?: any, ...optionalParams: any[]) => void ->console : Console ->log : (message?: any, ...optionalParams: any[]) => void + obj5; >obj5 : { foo: string; } & Child } } -function negative1() { ->negative1 : () => void +function exampleNegative() { +>exampleNegative : () => void class Parent { >Parent : Parent @@ -527,6 +293,10 @@ function negative1() { >obj : Parent | Parent | Child >Child : typeof Child + // Here we filter out matching ones, instead of just narrowing to them. + obj; +>obj : Child + return; } @@ -538,3 +308,99 @@ function negative1() { >obj : Parent | Parent } +function exampleIgnoreDefaults() { +>exampleIgnoreDefaults : () => void + + // default parameters shouldn't have any impact on this narrowing. + class Parent { +>Parent : Parent + + a: A; +>a : A + } + class Child extends Parent { +>Child : Child +>Parent : Parent + + a2: A2; +>a2 : A2 + + c: C; +>c : C + } + + const obj: Parent = undefined as any; +>obj : Parent +>undefined as any : any +>undefined : undefined + + if (obj instanceof Child) { +>obj instanceof Child : boolean +>obj : Parent +>Child : typeof Child + + obj; +>obj : Child + } +} + +function exampleConstraints() { +>exampleConstraints : () => void + + class Parent { +>Parent : Parent + + a: A; +>a : A + } + class Child extends Parent { +>Child : Child +>Parent : Parent + + b: B; +>b : B + } + + const objPass: Parent = undefined as any; +>objPass : Parent +>undefined as any : any +>undefined : undefined + + if (objPass instanceof Child) { +>objPass instanceof Child : boolean +>objPass : Parent +>Child : typeof Child + + objPass; +>objPass : Child + } + + const objFour: Parent<4> = undefined as any; +>objFour : Parent<4> +>undefined as any : any +>undefined : undefined + + if (objFour instanceof Child) { +>objFour instanceof Child : boolean +>objFour : Parent<4> +>Child : typeof Child + + objFour; +>objFour : Child + } + + const objFail: Parent = undefined as any; +>objFail : Parent +>undefined as any : any +>undefined : undefined + + if (objFail instanceof Child) { +>objFail instanceof Child : boolean +>objFail : Parent +>Child : typeof Child + + objFail; +>objFail : Child + } +} + diff --git a/tests/cases/compiler/narrowGenericTypeByInstanceOf.ts b/tests/cases/compiler/narrowGenericTypeByInstanceOf.ts index 2fce122aa7faf..6c09499e410dd 100644 --- a/tests/cases/compiler/narrowGenericTypeByInstanceOf.ts +++ b/tests/cases/compiler/narrowGenericTypeByInstanceOf.ts @@ -1,6 +1,4 @@ -import { stringify } from "querystring"; - -function example1() { +function exampleSingleArgument() { class Parent { value: T; } @@ -9,22 +7,13 @@ function example1() { other: T; } - const obj = new Parent(); - - function onlyChildNumber(child: Child) { - // no-op - } - function onlyChildString(child: Child) { - // no-op - } + const obj: Parent = undefined as any; if (obj instanceof Child) { - onlyChildNumber(obj); // should PASS - - onlyChildString(obj); // should ERROR: Child is not assignable to Child. + obj; } } -function example2() { +function exampleSingleExtendsMultiple() { class Parent { value1: A; value2: B; @@ -34,23 +23,14 @@ function example2() { other: T; } - const obj = new Parent(); - - function onlyChildNumber(child: Child) { - // no-op - } - function onlyChildString(child: Child) { - // no-op - } + const obj: Parent = undefined as any; if (obj instanceof Child) { - onlyChildNumber(obj); // should PASS - - onlyChildString(obj); // should ERROR: Child is not assignable to Child. + obj; } } -function example3() { +function exampleSwapParameterOrder() { class Parent { value1: A; value2: B; @@ -61,62 +41,14 @@ function example3() { value4: D; } - const obj = new Parent(); - - function onlyChildNumberString(child: Child) { - // no-op - } - function onlyChildStringNumber(child: Child) { - // no-op - } - function onlyChildNumberNumber(child: Child) { - // no-op - } + const obj: Parent = undefined as any; if (obj instanceof Child) { - onlyChildNumberString(obj); // should ERROR: Child is not assignable to Child. - onlyChildNumberNumber(obj); // should ERROR: Child is not assignable to Child. - - onlyChildStringNumber(obj); // should PASS - } -} - -function example4() { - class Parent { - value1: A; - value2: B; - } - - class Child extends Parent { - value3: C; - } - - const obj1 = new Parent(); - const obj2 = new Parent(); - - function onlyChildNumber(child: Child) { - // no-op - } - function onlyChildString(child: Child) { - // no-op - } - function onlyChildStringAndNumber(child: Child) { - // no-op - } - - if (obj1 instanceof Child) { - onlyChildNumber(obj1); - onlyChildString(obj1); - onlyChildStringAndNumber(obj1); - } - if (obj2 instanceof Child) { - onlyChildNumber(obj2); - onlyChildString(obj2); - onlyChildStringAndNumber(obj2); + obj; } } -function example5() { +function exampleSingleExtendsMultipleReject() { class Parent { value1: A; value2: B; @@ -126,26 +58,14 @@ function example5() { value3: C; } - const obj = new Parent(); - - function onlyChildS(child: Child) { - // no-op - } - function onlyChildT(child: Child) { - // no-op - } - function onlyChildSAndT(child: Child) { - // no-op - } + const obj: Parent = undefined as any; if (obj instanceof Child) { - onlyChildS(obj); - onlyChildT(obj); - onlyChildSAndT(obj); + obj; } } -function example6() { +function exampleUnion() { class Parent { value1: A; value2: B; @@ -155,47 +75,40 @@ function example6() { value3: C; } - const obj: + const obj0: | Parent<{ foo: string }, { foo: string }> | Parent | Parent = undefined as any; - - const obj1 = undefined as Parent<{ foo: string }, { foo: string }>; - const obj2 = undefined as Parent; - const obj3 = undefined as Parent; - const obj4 = undefined as string | { foo: string }; - const obj5 = undefined as { foo: string }; - - function onlyChildString(child: Child) { - // no-op - } - function onlyChildNumber(child: Child) { - // no-op - } - - if (obj instanceof Child) { - onlyChildString(obj); - onlyChildNumber(obj); + if (obj0 instanceof Child) { + obj0; } + const obj1 = undefined as Parent<{ foo: string }, { foo: string }>; if (obj1 instanceof Child) { - console.log(obj1); + obj1; } + + const obj2 = undefined as Parent; if (obj2 instanceof Child) { - console.log(obj2); + obj2; } + + const obj3 = undefined as Parent; if (obj3 instanceof Child) { - console.log(obj3); + obj3; } + + const obj4 = undefined as string | { foo: string }; if (obj4 instanceof Child) { - console.log(obj4); + obj4; } + const obj5 = undefined as { foo: string }; if (obj5 instanceof Child) { - console.log(obj5); + obj5; } } -function negative1() { +function exampleNegative() { class Parent { value1: A; value2: B; @@ -211,8 +124,50 @@ function negative1() { | Child = undefined as any; if (obj instanceof Child) { + // Here we filter out matching ones, instead of just narrowing to them. + obj; return; } console.log(obj); } + +function exampleIgnoreDefaults() { + // default parameters shouldn't have any impact on this narrowing. + class Parent { + a: A; + } + class Child extends Parent { + a2: A2; + c: C; + } + + const obj: Parent = undefined as any; + if (obj instanceof Child) { + obj; + } +} + +function exampleConstraints() { + class Parent { + a: A; + } + class Child extends Parent { + b: B; + } + + const objPass: Parent = undefined as any; + if (objPass instanceof Child) { + objPass; + } + + const objFour: Parent<4> = undefined as any; + if (objFour instanceof Child) { + objFour; + } + + const objFail: Parent = undefined as any; + if (objFail instanceof Child) { + objFail; + } +} From 52d81cea74983fadb0a28769107318ad22f2e701 Mon Sep 17 00:00:00 2001 From: Nathan Fenner Date: Tue, 26 Feb 2019 11:37:13 -0800 Subject: [PATCH 3/5] narrowGenericTypeByInstance test update --- .../narrowGenericTypeByInstanceOf.js | 69 +++++++++++ .../narrowGenericTypeByInstanceOf.symbols | 98 +++++++++++++++ .../narrowGenericTypeByInstanceOf.types | 117 ++++++++++++++++++ .../compiler/narrowGenericTypeByInstanceOf.ts | 38 ++++++ 4 files changed, 322 insertions(+) diff --git a/tests/baselines/reference/narrowGenericTypeByInstanceOf.js b/tests/baselines/reference/narrowGenericTypeByInstanceOf.js index 4f09a8f64112b..b643a69e1f88c 100644 --- a/tests/baselines/reference/narrowGenericTypeByInstanceOf.js +++ b/tests/baselines/reference/narrowGenericTypeByInstanceOf.js @@ -172,6 +172,44 @@ function exampleConstraints() { objFail; } } + +function exampleUnrelated() { + class Child { + a: A; + b: B; + foo: number; + } + + const objA = { a: 5 }; + if (objA instanceof Child) { + objA; // Child + } + + const objB = { b: "hello" }; + if (objB instanceof Child) { + objB; // Child + } + + const objAB = { a: 5, b: "hello" }; + if (objAB instanceof Child) { + objAB; // Child + } + + const objAX = { a: 5, x: 7 }; + if (objAX instanceof Child) { + objAX; // Child + } + + const objBX = { b: "hello", x: 7 }; + if (objBX instanceof Child) { + objBX; // Child + } + + const objABX = { a: 5, b: "hello", x: 7 }; + if (objABX instanceof Child) { + objABX; // Child + } +} //// [narrowGenericTypeByInstanceOf.js] @@ -364,3 +402,34 @@ function exampleConstraints() { objFail; } } +function exampleUnrelated() { + var Child = /** @class */ (function () { + function Child() { + } + return Child; + }()); + var objA = { a: 5 }; + if (objA instanceof Child) { + objA; // Child + } + var objB = { b: "hello" }; + if (objB instanceof Child) { + objB; // Child + } + var objAB = { a: 5, b: "hello" }; + if (objAB instanceof Child) { + objAB; // Child + } + var objAX = { a: 5, x: 7 }; + if (objAX instanceof Child) { + objAX; // Child + } + var objBX = { b: "hello", x: 7 }; + if (objBX instanceof Child) { + objBX; // Child + } + var objABX = { a: 5, b: "hello", x: 7 }; + if (objABX instanceof Child) { + objABX; // Child + } +} diff --git a/tests/baselines/reference/narrowGenericTypeByInstanceOf.symbols b/tests/baselines/reference/narrowGenericTypeByInstanceOf.symbols index add6ed52ea1e4..242a54bd865cf 100644 --- a/tests/baselines/reference/narrowGenericTypeByInstanceOf.symbols +++ b/tests/baselines/reference/narrowGenericTypeByInstanceOf.symbols @@ -452,3 +452,101 @@ function exampleConstraints() { } } +function exampleUnrelated() { +>exampleUnrelated : Symbol(exampleUnrelated, Decl(narrowGenericTypeByInstanceOf.ts, 172, 1)) + + class Child { +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 174, 29)) +>A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 175, 14)) +>B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 175, 16)) + + a: A; +>a : Symbol(Child.a, Decl(narrowGenericTypeByInstanceOf.ts, 175, 21)) +>A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 175, 14)) + + b: B; +>b : Symbol(Child.b, Decl(narrowGenericTypeByInstanceOf.ts, 176, 9)) +>B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 175, 16)) + + foo: number; +>foo : Symbol(Child.foo, Decl(narrowGenericTypeByInstanceOf.ts, 177, 9)) + } + + const objA = { a: 5 }; +>objA : Symbol(objA, Decl(narrowGenericTypeByInstanceOf.ts, 181, 7)) +>a : Symbol(a, Decl(narrowGenericTypeByInstanceOf.ts, 181, 16)) + + if (objA instanceof Child) { +>objA : Symbol(objA, Decl(narrowGenericTypeByInstanceOf.ts, 181, 7)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 174, 29)) + + objA; // Child +>objA : Symbol(objA, Decl(narrowGenericTypeByInstanceOf.ts, 181, 7)) + } + + const objB = { b: "hello" }; +>objB : Symbol(objB, Decl(narrowGenericTypeByInstanceOf.ts, 186, 7)) +>b : Symbol(b, Decl(narrowGenericTypeByInstanceOf.ts, 186, 16)) + + if (objB instanceof Child) { +>objB : Symbol(objB, Decl(narrowGenericTypeByInstanceOf.ts, 186, 7)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 174, 29)) + + objB; // Child +>objB : Symbol(objB, Decl(narrowGenericTypeByInstanceOf.ts, 186, 7)) + } + + const objAB = { a: 5, b: "hello" }; +>objAB : Symbol(objAB, Decl(narrowGenericTypeByInstanceOf.ts, 191, 7)) +>a : Symbol(a, Decl(narrowGenericTypeByInstanceOf.ts, 191, 17)) +>b : Symbol(b, Decl(narrowGenericTypeByInstanceOf.ts, 191, 23)) + + if (objAB instanceof Child) { +>objAB : Symbol(objAB, Decl(narrowGenericTypeByInstanceOf.ts, 191, 7)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 174, 29)) + + objAB; // Child +>objAB : Symbol(objAB, Decl(narrowGenericTypeByInstanceOf.ts, 191, 7)) + } + + const objAX = { a: 5, x: 7 }; +>objAX : Symbol(objAX, Decl(narrowGenericTypeByInstanceOf.ts, 196, 7)) +>a : Symbol(a, Decl(narrowGenericTypeByInstanceOf.ts, 196, 17)) +>x : Symbol(x, Decl(narrowGenericTypeByInstanceOf.ts, 196, 23)) + + if (objAX instanceof Child) { +>objAX : Symbol(objAX, Decl(narrowGenericTypeByInstanceOf.ts, 196, 7)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 174, 29)) + + objAX; // Child +>objAX : Symbol(objAX, Decl(narrowGenericTypeByInstanceOf.ts, 196, 7)) + } + + const objBX = { b: "hello", x: 7 }; +>objBX : Symbol(objBX, Decl(narrowGenericTypeByInstanceOf.ts, 201, 7)) +>b : Symbol(b, Decl(narrowGenericTypeByInstanceOf.ts, 201, 17)) +>x : Symbol(x, Decl(narrowGenericTypeByInstanceOf.ts, 201, 29)) + + if (objBX instanceof Child) { +>objBX : Symbol(objBX, Decl(narrowGenericTypeByInstanceOf.ts, 201, 7)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 174, 29)) + + objBX; // Child +>objBX : Symbol(objBX, Decl(narrowGenericTypeByInstanceOf.ts, 201, 7)) + } + + const objABX = { a: 5, b: "hello", x: 7 }; +>objABX : Symbol(objABX, Decl(narrowGenericTypeByInstanceOf.ts, 206, 7)) +>a : Symbol(a, Decl(narrowGenericTypeByInstanceOf.ts, 206, 18)) +>b : Symbol(b, Decl(narrowGenericTypeByInstanceOf.ts, 206, 24)) +>x : Symbol(x, Decl(narrowGenericTypeByInstanceOf.ts, 206, 36)) + + if (objABX instanceof Child) { +>objABX : Symbol(objABX, Decl(narrowGenericTypeByInstanceOf.ts, 206, 7)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 174, 29)) + + objABX; // Child +>objABX : Symbol(objABX, Decl(narrowGenericTypeByInstanceOf.ts, 206, 7)) + } +} + diff --git a/tests/baselines/reference/narrowGenericTypeByInstanceOf.types b/tests/baselines/reference/narrowGenericTypeByInstanceOf.types index 31bb3c4b75e01..b69f5834cb736 100644 --- a/tests/baselines/reference/narrowGenericTypeByInstanceOf.types +++ b/tests/baselines/reference/narrowGenericTypeByInstanceOf.types @@ -404,3 +404,120 @@ function exampleConstraints() { } } +function exampleUnrelated() { +>exampleUnrelated : () => void + + class Child { +>Child : Child + + a: A; +>a : A + + b: B; +>b : B + + foo: number; +>foo : number + } + + const objA = { a: 5 }; +>objA : { a: number; } +>{ a: 5 } : { a: number; } +>a : number +>5 : 5 + + if (objA instanceof Child) { +>objA instanceof Child : boolean +>objA : { a: number; } +>Child : typeof Child + + objA; // Child +>objA : Child + } + + const objB = { b: "hello" }; +>objB : { b: string; } +>{ b: "hello" } : { b: string; } +>b : string +>"hello" : "hello" + + if (objB instanceof Child) { +>objB instanceof Child : boolean +>objB : { b: string; } +>Child : typeof Child + + objB; // Child +>objB : Child + } + + const objAB = { a: 5, b: "hello" }; +>objAB : { a: number; b: string; } +>{ a: 5, b: "hello" } : { a: number; b: string; } +>a : number +>5 : 5 +>b : string +>"hello" : "hello" + + if (objAB instanceof Child) { +>objAB instanceof Child : boolean +>objAB : { a: number; b: string; } +>Child : typeof Child + + objAB; // Child +>objAB : Child + } + + const objAX = { a: 5, x: 7 }; +>objAX : { a: number; x: number; } +>{ a: 5, x: 7 } : { a: number; x: number; } +>a : number +>5 : 5 +>x : number +>7 : 7 + + if (objAX instanceof Child) { +>objAX instanceof Child : boolean +>objAX : { a: number; x: number; } +>Child : typeof Child + + objAX; // Child +>objAX : { a: number; x: number; } & Child + } + + const objBX = { b: "hello", x: 7 }; +>objBX : { b: string; x: number; } +>{ b: "hello", x: 7 } : { b: string; x: number; } +>b : string +>"hello" : "hello" +>x : number +>7 : 7 + + if (objBX instanceof Child) { +>objBX instanceof Child : boolean +>objBX : { b: string; x: number; } +>Child : typeof Child + + objBX; // Child +>objBX : { b: string; x: number; } & Child + } + + const objABX = { a: 5, b: "hello", x: 7 }; +>objABX : { a: number; b: string; x: number; } +>{ a: 5, b: "hello", x: 7 } : { a: number; b: string; x: number; } +>a : number +>5 : 5 +>b : string +>"hello" : "hello" +>x : number +>7 : 7 + + if (objABX instanceof Child) { +>objABX instanceof Child : boolean +>objABX : { a: number; b: string; x: number; } +>Child : typeof Child + + objABX; // Child +>objABX : { a: number; b: string; x: number; } & Child + } +} + diff --git a/tests/cases/compiler/narrowGenericTypeByInstanceOf.ts b/tests/cases/compiler/narrowGenericTypeByInstanceOf.ts index 6c09499e410dd..dd18c0a9834e4 100644 --- a/tests/cases/compiler/narrowGenericTypeByInstanceOf.ts +++ b/tests/cases/compiler/narrowGenericTypeByInstanceOf.ts @@ -171,3 +171,41 @@ function exampleConstraints() { objFail; } } + +function exampleUnrelated() { + class Child { + a: A; + b: B; + foo: number; + } + + const objA = { a: 5 }; + if (objA instanceof Child) { + objA; // Child + } + + const objB = { b: "hello" }; + if (objB instanceof Child) { + objB; // Child + } + + const objAB = { a: 5, b: "hello" }; + if (objAB instanceof Child) { + objAB; // Child + } + + const objAX = { a: 5, x: 7 }; + if (objAX instanceof Child) { + objAX; // Child + } + + const objBX = { b: "hello", x: 7 }; + if (objBX instanceof Child) { + objBX; // Child + } + + const objABX = { a: 5, b: "hello", x: 7 }; + if (objABX instanceof Child) { + objABX; // Child + } +} From f133aedffacabfa348cc9d918976c7106c1377b5 Mon Sep 17 00:00:00 2001 From: Nathan Fenner Date: Thu, 28 Feb 2019 13:48:24 -0800 Subject: [PATCH 4/5] update narrowing tests for constrained children types --- src/compiler/checker.ts | 5 +- .../narrowGenericTypeByInstanceOf.js | 51 ++++-- .../narrowGenericTypeByInstanceOf.symbols | 149 +++++++++++------- .../narrowGenericTypeByInstanceOf.types | 70 ++++++-- .../compiler/narrowGenericTypeByInstanceOf.ts | 29 +++- 5 files changed, 214 insertions(+), 90 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index db546c3247e8e..d9d16eb3502c4 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -16071,7 +16071,8 @@ namespace ts { ); // Infer the types from superType onto the return type of the child constructor. - inferTypes(inferenceContext.inferences, superType, getReturnTypeOfSignature(childConstructor), InferencePriority.ReturnType); + const childTemplateType = getReturnTypeOfSignature(childConstructor); + inferTypes(inferenceContext.inferences, superType, childTemplateType, InferencePriority.NakedTypeVariable); // We extract the inferred arguments from the inference context. // silentNeverType indicates that no type could be inferred. @@ -16080,7 +16081,7 @@ namespace ts { // Lastly, supply the childType with the new parameters. - return instantiateType(getReturnTypeOfSignature(childConstructor), param => { + return instantiateType(childTemplateType, param => { if (childTypeParameters.indexOf(param) >= 0) { return childArguments[childTypeParameters.indexOf(param)]; } diff --git a/tests/baselines/reference/narrowGenericTypeByInstanceOf.js b/tests/baselines/reference/narrowGenericTypeByInstanceOf.js index b643a69e1f88c..b77e3b8ec51fe 100644 --- a/tests/baselines/reference/narrowGenericTypeByInstanceOf.js +++ b/tests/baselines/reference/narrowGenericTypeByInstanceOf.js @@ -153,23 +153,38 @@ function exampleConstraints() { class Parent { a: A; } - class Child extends Parent { + class Child extends Parent { b: B; } - const objPass: Parent = undefined as any; + const objPass: Parent<1 | 2 | 3> = undefined as any; if (objPass instanceof Child) { - objPass; + objPass; // expect: Child<1 | 2 | 3> } - const objFour: Parent<4> = undefined as any; - if (objFour instanceof Child) { - objFour; + const obj12: Parent<1 | 2> = undefined as any; + if (obj12 instanceof Child) { + obj12; // expect: Child<1 | 2> } const objFail: Parent = undefined as any; if (objFail instanceof Child) { - objFail; + objFail; // Child, since string and 1|2|3 have no overlap. + } + + const objRefine: Parent = undefined as any; + if (objRefine instanceof Child) { + objRefine; // expect: Child<1 | 2 | 3> + } + + const objRefine1234: Parent<1 | 2 | 3 | 4> = undefined as any; + if (objRefine1234 instanceof Child) { + objRefine1234; // expect: Child<1 | 2 | 3> + } + + const objOverlap: Parent<2 | 3 | 4 | 5> = undefined as any; + if (objOverlap instanceof Child) { + objOverlap; // ideally, Child<2 | 3>, but actually Child since 2|3|4|5 is not a supertype of 1|2|3. } } @@ -391,15 +406,27 @@ function exampleConstraints() { }(Parent)); var objPass = undefined; if (objPass instanceof Child) { - objPass; + objPass; // expect: Child<1 | 2 | 3> } - var objFour = undefined; - if (objFour instanceof Child) { - objFour; + var obj12 = undefined; + if (obj12 instanceof Child) { + obj12; // expect: Child<1 | 2> } var objFail = undefined; if (objFail instanceof Child) { - objFail; + objFail; // Child, since string and 1|2|3 have no overlap. + } + var objRefine = undefined; + if (objRefine instanceof Child) { + objRefine; // expect: Child<1 | 2 | 3> + } + var objRefine1234 = undefined; + if (objRefine1234 instanceof Child) { + objRefine1234; // expect: Child<1 | 2 | 3> + } + var objOverlap = undefined; + if (objOverlap instanceof Child) { + objOverlap; // ideally, Child<2 | 3>, but actually Child since 2|3|4|5 is not a supertype of 1|2|3. } } function exampleUnrelated() { diff --git a/tests/baselines/reference/narrowGenericTypeByInstanceOf.symbols b/tests/baselines/reference/narrowGenericTypeByInstanceOf.symbols index 242a54bd865cf..f49bb5ee2d71f 100644 --- a/tests/baselines/reference/narrowGenericTypeByInstanceOf.symbols +++ b/tests/baselines/reference/narrowGenericTypeByInstanceOf.symbols @@ -401,18 +401,18 @@ function exampleConstraints() { >a : Symbol(Parent.a, Decl(narrowGenericTypeByInstanceOf.ts, 151, 19)) >A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 151, 15)) } - class Child extends Parent { + class Child extends Parent { >Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 153, 3)) >B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 154, 14)) >Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 150, 31)) >B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 154, 14)) b: B; ->b : Symbol(Child.b, Decl(narrowGenericTypeByInstanceOf.ts, 154, 51)) +>b : Symbol(Child.b, Decl(narrowGenericTypeByInstanceOf.ts, 154, 54)) >B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 154, 14)) } - const objPass: Parent = undefined as any; + const objPass: Parent<1 | 2 | 3> = undefined as any; >objPass : Symbol(objPass, Decl(narrowGenericTypeByInstanceOf.ts, 158, 7)) >Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 150, 31)) >undefined : Symbol(undefined) @@ -421,21 +421,21 @@ function exampleConstraints() { >objPass : Symbol(objPass, Decl(narrowGenericTypeByInstanceOf.ts, 158, 7)) >Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 153, 3)) - objPass; + objPass; // expect: Child<1 | 2 | 3> >objPass : Symbol(objPass, Decl(narrowGenericTypeByInstanceOf.ts, 158, 7)) } - const objFour: Parent<4> = undefined as any; ->objFour : Symbol(objFour, Decl(narrowGenericTypeByInstanceOf.ts, 163, 7)) + const obj12: Parent<1 | 2> = undefined as any; +>obj12 : Symbol(obj12, Decl(narrowGenericTypeByInstanceOf.ts, 163, 7)) >Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 150, 31)) >undefined : Symbol(undefined) - if (objFour instanceof Child) { ->objFour : Symbol(objFour, Decl(narrowGenericTypeByInstanceOf.ts, 163, 7)) + if (obj12 instanceof Child) { +>obj12 : Symbol(obj12, Decl(narrowGenericTypeByInstanceOf.ts, 163, 7)) >Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 153, 3)) - objFour; ->objFour : Symbol(objFour, Decl(narrowGenericTypeByInstanceOf.ts, 163, 7)) + obj12; // expect: Child<1 | 2> +>obj12 : Symbol(obj12, Decl(narrowGenericTypeByInstanceOf.ts, 163, 7)) } const objFail: Parent = undefined as any; @@ -447,106 +447,145 @@ function exampleConstraints() { >objFail : Symbol(objFail, Decl(narrowGenericTypeByInstanceOf.ts, 168, 7)) >Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 153, 3)) - objFail; + objFail; // Child, since string and 1|2|3 have no overlap. >objFail : Symbol(objFail, Decl(narrowGenericTypeByInstanceOf.ts, 168, 7)) } + + const objRefine: Parent = undefined as any; +>objRefine : Symbol(objRefine, Decl(narrowGenericTypeByInstanceOf.ts, 173, 7)) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 150, 31)) +>undefined : Symbol(undefined) + + if (objRefine instanceof Child) { +>objRefine : Symbol(objRefine, Decl(narrowGenericTypeByInstanceOf.ts, 173, 7)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 153, 3)) + + objRefine; // expect: Child<1 | 2 | 3> +>objRefine : Symbol(objRefine, Decl(narrowGenericTypeByInstanceOf.ts, 173, 7)) + } + + const objRefine1234: Parent<1 | 2 | 3 | 4> = undefined as any; +>objRefine1234 : Symbol(objRefine1234, Decl(narrowGenericTypeByInstanceOf.ts, 178, 7)) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 150, 31)) +>undefined : Symbol(undefined) + + if (objRefine1234 instanceof Child) { +>objRefine1234 : Symbol(objRefine1234, Decl(narrowGenericTypeByInstanceOf.ts, 178, 7)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 153, 3)) + + objRefine1234; // expect: Child<1 | 2 | 3> +>objRefine1234 : Symbol(objRefine1234, Decl(narrowGenericTypeByInstanceOf.ts, 178, 7)) + } + + const objOverlap: Parent<2 | 3 | 4 | 5> = undefined as any; +>objOverlap : Symbol(objOverlap, Decl(narrowGenericTypeByInstanceOf.ts, 183, 7)) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 150, 31)) +>undefined : Symbol(undefined) + + if (objOverlap instanceof Child) { +>objOverlap : Symbol(objOverlap, Decl(narrowGenericTypeByInstanceOf.ts, 183, 7)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 153, 3)) + + objOverlap; // ideally, Child<2 | 3>, but actually Child since 2|3|4|5 is not a supertype of 1|2|3. +>objOverlap : Symbol(objOverlap, Decl(narrowGenericTypeByInstanceOf.ts, 183, 7)) + } } function exampleUnrelated() { ->exampleUnrelated : Symbol(exampleUnrelated, Decl(narrowGenericTypeByInstanceOf.ts, 172, 1)) +>exampleUnrelated : Symbol(exampleUnrelated, Decl(narrowGenericTypeByInstanceOf.ts, 187, 1)) class Child { ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 174, 29)) ->A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 175, 14)) ->B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 175, 16)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 189, 29)) +>A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 190, 14)) +>B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 190, 16)) a: A; ->a : Symbol(Child.a, Decl(narrowGenericTypeByInstanceOf.ts, 175, 21)) ->A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 175, 14)) +>a : Symbol(Child.a, Decl(narrowGenericTypeByInstanceOf.ts, 190, 21)) +>A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 190, 14)) b: B; ->b : Symbol(Child.b, Decl(narrowGenericTypeByInstanceOf.ts, 176, 9)) ->B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 175, 16)) +>b : Symbol(Child.b, Decl(narrowGenericTypeByInstanceOf.ts, 191, 9)) +>B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 190, 16)) foo: number; ->foo : Symbol(Child.foo, Decl(narrowGenericTypeByInstanceOf.ts, 177, 9)) +>foo : Symbol(Child.foo, Decl(narrowGenericTypeByInstanceOf.ts, 192, 9)) } const objA = { a: 5 }; ->objA : Symbol(objA, Decl(narrowGenericTypeByInstanceOf.ts, 181, 7)) ->a : Symbol(a, Decl(narrowGenericTypeByInstanceOf.ts, 181, 16)) +>objA : Symbol(objA, Decl(narrowGenericTypeByInstanceOf.ts, 196, 7)) +>a : Symbol(a, Decl(narrowGenericTypeByInstanceOf.ts, 196, 16)) if (objA instanceof Child) { ->objA : Symbol(objA, Decl(narrowGenericTypeByInstanceOf.ts, 181, 7)) ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 174, 29)) +>objA : Symbol(objA, Decl(narrowGenericTypeByInstanceOf.ts, 196, 7)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 189, 29)) objA; // Child ->objA : Symbol(objA, Decl(narrowGenericTypeByInstanceOf.ts, 181, 7)) +>objA : Symbol(objA, Decl(narrowGenericTypeByInstanceOf.ts, 196, 7)) } const objB = { b: "hello" }; ->objB : Symbol(objB, Decl(narrowGenericTypeByInstanceOf.ts, 186, 7)) ->b : Symbol(b, Decl(narrowGenericTypeByInstanceOf.ts, 186, 16)) +>objB : Symbol(objB, Decl(narrowGenericTypeByInstanceOf.ts, 201, 7)) +>b : Symbol(b, Decl(narrowGenericTypeByInstanceOf.ts, 201, 16)) if (objB instanceof Child) { ->objB : Symbol(objB, Decl(narrowGenericTypeByInstanceOf.ts, 186, 7)) ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 174, 29)) +>objB : Symbol(objB, Decl(narrowGenericTypeByInstanceOf.ts, 201, 7)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 189, 29)) objB; // Child ->objB : Symbol(objB, Decl(narrowGenericTypeByInstanceOf.ts, 186, 7)) +>objB : Symbol(objB, Decl(narrowGenericTypeByInstanceOf.ts, 201, 7)) } const objAB = { a: 5, b: "hello" }; ->objAB : Symbol(objAB, Decl(narrowGenericTypeByInstanceOf.ts, 191, 7)) ->a : Symbol(a, Decl(narrowGenericTypeByInstanceOf.ts, 191, 17)) ->b : Symbol(b, Decl(narrowGenericTypeByInstanceOf.ts, 191, 23)) +>objAB : Symbol(objAB, Decl(narrowGenericTypeByInstanceOf.ts, 206, 7)) +>a : Symbol(a, Decl(narrowGenericTypeByInstanceOf.ts, 206, 17)) +>b : Symbol(b, Decl(narrowGenericTypeByInstanceOf.ts, 206, 23)) if (objAB instanceof Child) { ->objAB : Symbol(objAB, Decl(narrowGenericTypeByInstanceOf.ts, 191, 7)) ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 174, 29)) +>objAB : Symbol(objAB, Decl(narrowGenericTypeByInstanceOf.ts, 206, 7)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 189, 29)) objAB; // Child ->objAB : Symbol(objAB, Decl(narrowGenericTypeByInstanceOf.ts, 191, 7)) +>objAB : Symbol(objAB, Decl(narrowGenericTypeByInstanceOf.ts, 206, 7)) } const objAX = { a: 5, x: 7 }; ->objAX : Symbol(objAX, Decl(narrowGenericTypeByInstanceOf.ts, 196, 7)) ->a : Symbol(a, Decl(narrowGenericTypeByInstanceOf.ts, 196, 17)) ->x : Symbol(x, Decl(narrowGenericTypeByInstanceOf.ts, 196, 23)) +>objAX : Symbol(objAX, Decl(narrowGenericTypeByInstanceOf.ts, 211, 7)) +>a : Symbol(a, Decl(narrowGenericTypeByInstanceOf.ts, 211, 17)) +>x : Symbol(x, Decl(narrowGenericTypeByInstanceOf.ts, 211, 23)) if (objAX instanceof Child) { ->objAX : Symbol(objAX, Decl(narrowGenericTypeByInstanceOf.ts, 196, 7)) ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 174, 29)) +>objAX : Symbol(objAX, Decl(narrowGenericTypeByInstanceOf.ts, 211, 7)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 189, 29)) objAX; // Child ->objAX : Symbol(objAX, Decl(narrowGenericTypeByInstanceOf.ts, 196, 7)) +>objAX : Symbol(objAX, Decl(narrowGenericTypeByInstanceOf.ts, 211, 7)) } const objBX = { b: "hello", x: 7 }; ->objBX : Symbol(objBX, Decl(narrowGenericTypeByInstanceOf.ts, 201, 7)) ->b : Symbol(b, Decl(narrowGenericTypeByInstanceOf.ts, 201, 17)) ->x : Symbol(x, Decl(narrowGenericTypeByInstanceOf.ts, 201, 29)) +>objBX : Symbol(objBX, Decl(narrowGenericTypeByInstanceOf.ts, 216, 7)) +>b : Symbol(b, Decl(narrowGenericTypeByInstanceOf.ts, 216, 17)) +>x : Symbol(x, Decl(narrowGenericTypeByInstanceOf.ts, 216, 29)) if (objBX instanceof Child) { ->objBX : Symbol(objBX, Decl(narrowGenericTypeByInstanceOf.ts, 201, 7)) ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 174, 29)) +>objBX : Symbol(objBX, Decl(narrowGenericTypeByInstanceOf.ts, 216, 7)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 189, 29)) objBX; // Child ->objBX : Symbol(objBX, Decl(narrowGenericTypeByInstanceOf.ts, 201, 7)) +>objBX : Symbol(objBX, Decl(narrowGenericTypeByInstanceOf.ts, 216, 7)) } const objABX = { a: 5, b: "hello", x: 7 }; ->objABX : Symbol(objABX, Decl(narrowGenericTypeByInstanceOf.ts, 206, 7)) ->a : Symbol(a, Decl(narrowGenericTypeByInstanceOf.ts, 206, 18)) ->b : Symbol(b, Decl(narrowGenericTypeByInstanceOf.ts, 206, 24)) ->x : Symbol(x, Decl(narrowGenericTypeByInstanceOf.ts, 206, 36)) +>objABX : Symbol(objABX, Decl(narrowGenericTypeByInstanceOf.ts, 221, 7)) +>a : Symbol(a, Decl(narrowGenericTypeByInstanceOf.ts, 221, 18)) +>b : Symbol(b, Decl(narrowGenericTypeByInstanceOf.ts, 221, 24)) +>x : Symbol(x, Decl(narrowGenericTypeByInstanceOf.ts, 221, 36)) if (objABX instanceof Child) { ->objABX : Symbol(objABX, Decl(narrowGenericTypeByInstanceOf.ts, 206, 7)) ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 174, 29)) +>objABX : Symbol(objABX, Decl(narrowGenericTypeByInstanceOf.ts, 221, 7)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 189, 29)) objABX; // Child ->objABX : Symbol(objABX, Decl(narrowGenericTypeByInstanceOf.ts, 206, 7)) +>objABX : Symbol(objABX, Decl(narrowGenericTypeByInstanceOf.ts, 221, 7)) } } diff --git a/tests/baselines/reference/narrowGenericTypeByInstanceOf.types b/tests/baselines/reference/narrowGenericTypeByInstanceOf.types index b69f5834cb736..0c2884234ca60 100644 --- a/tests/baselines/reference/narrowGenericTypeByInstanceOf.types +++ b/tests/baselines/reference/narrowGenericTypeByInstanceOf.types @@ -353,7 +353,7 @@ function exampleConstraints() { a: A; >a : A } - class Child extends Parent { + class Child extends Parent { >Child : Child >Parent : Parent @@ -361,32 +361,32 @@ function exampleConstraints() { >b : B } - const objPass: Parent = undefined as any; ->objPass : Parent + const objPass: Parent<1 | 2 | 3> = undefined as any; +>objPass : Parent<1 | 2 | 3> >undefined as any : any >undefined : undefined if (objPass instanceof Child) { >objPass instanceof Child : boolean ->objPass : Parent +>objPass : Parent<1 | 2 | 3> >Child : typeof Child - objPass; ->objPass : Child + objPass; // expect: Child<1 | 2 | 3> +>objPass : Child<1 | 2 | 3> } - const objFour: Parent<4> = undefined as any; ->objFour : Parent<4> + const obj12: Parent<1 | 2> = undefined as any; +>obj12 : Parent<1 | 2> >undefined as any : any >undefined : undefined - if (objFour instanceof Child) { ->objFour instanceof Child : boolean ->objFour : Parent<4> + if (obj12 instanceof Child) { +>obj12 instanceof Child : boolean +>obj12 : Parent<1 | 2> >Child : typeof Child - objFour; ->objFour : Child + obj12; // expect: Child<1 | 2> +>obj12 : Child<1 | 2> } const objFail: Parent = undefined as any; @@ -399,9 +399,51 @@ function exampleConstraints() { >objFail : Parent >Child : typeof Child - objFail; + objFail; // Child, since string and 1|2|3 have no overlap. >objFail : Child } + + const objRefine: Parent = undefined as any; +>objRefine : Parent +>undefined as any : any +>undefined : undefined + + if (objRefine instanceof Child) { +>objRefine instanceof Child : boolean +>objRefine : Parent +>Child : typeof Child + + objRefine; // expect: Child<1 | 2 | 3> +>objRefine : Child<1 | 2 | 3> + } + + const objRefine1234: Parent<1 | 2 | 3 | 4> = undefined as any; +>objRefine1234 : Parent<1 | 2 | 3 | 4> +>undefined as any : any +>undefined : undefined + + if (objRefine1234 instanceof Child) { +>objRefine1234 instanceof Child : boolean +>objRefine1234 : Parent<1 | 2 | 3 | 4> +>Child : typeof Child + + objRefine1234; // expect: Child<1 | 2 | 3> +>objRefine1234 : Child<1 | 2 | 3> + } + + const objOverlap: Parent<2 | 3 | 4 | 5> = undefined as any; +>objOverlap : Parent<2 | 3 | 4 | 5> +>undefined as any : any +>undefined : undefined + + if (objOverlap instanceof Child) { +>objOverlap instanceof Child : boolean +>objOverlap : Parent<2 | 3 | 4 | 5> +>Child : typeof Child + + objOverlap; // ideally, Child<2 | 3>, but actually Child since 2|3|4|5 is not a supertype of 1|2|3. +>objOverlap : Child + } } function exampleUnrelated() { diff --git a/tests/cases/compiler/narrowGenericTypeByInstanceOf.ts b/tests/cases/compiler/narrowGenericTypeByInstanceOf.ts index dd18c0a9834e4..1cc65e29a78a0 100644 --- a/tests/cases/compiler/narrowGenericTypeByInstanceOf.ts +++ b/tests/cases/compiler/narrowGenericTypeByInstanceOf.ts @@ -152,23 +152,38 @@ function exampleConstraints() { class Parent { a: A; } - class Child extends Parent { + class Child extends Parent { b: B; } - const objPass: Parent = undefined as any; + const objPass: Parent<1 | 2 | 3> = undefined as any; if (objPass instanceof Child) { - objPass; + objPass; // expect: Child<1 | 2 | 3> } - const objFour: Parent<4> = undefined as any; - if (objFour instanceof Child) { - objFour; + const obj12: Parent<1 | 2> = undefined as any; + if (obj12 instanceof Child) { + obj12; // expect: Child<1 | 2> } const objFail: Parent = undefined as any; if (objFail instanceof Child) { - objFail; + objFail; // Child, since string and 1|2|3 have no overlap. + } + + const objRefine: Parent = undefined as any; + if (objRefine instanceof Child) { + objRefine; // expect: Child<1 | 2 | 3> + } + + const objRefine1234: Parent<1 | 2 | 3 | 4> = undefined as any; + if (objRefine1234 instanceof Child) { + objRefine1234; // expect: Child<1 | 2 | 3> + } + + const objOverlap: Parent<2 | 3 | 4 | 5> = undefined as any; + if (objOverlap instanceof Child) { + objOverlap; // ideally, Child<2 | 3>, but actually Child since 2|3|4|5 is not a supertype of 1|2|3. } } From d3d5198c452f8ca9e841020aa559bd2f093b4c94 Mon Sep 17 00:00:00 2001 From: Nathan Fenner Date: Tue, 7 May 2019 15:09:47 -0700 Subject: [PATCH 5/5] update narrowGenericTypeByInstance test --- .../narrowGenericTypeByInstanceOf.js | 587 ++++++------ .../narrowGenericTypeByInstanceOf.symbols | 863 ++++++++---------- .../narrowGenericTypeByInstanceOf.types | 719 ++++++--------- .../compiler/narrowGenericTypeByInstanceOf.ts | 316 +++---- 4 files changed, 1123 insertions(+), 1362 deletions(-) diff --git a/tests/baselines/reference/narrowGenericTypeByInstanceOf.js b/tests/baselines/reference/narrowGenericTypeByInstanceOf.js index b77e3b8ec51fe..5579e6b7bb789 100644 --- a/tests/baselines/reference/narrowGenericTypeByInstanceOf.js +++ b/tests/baselines/reference/narrowGenericTypeByInstanceOf.js @@ -1,233 +1,208 @@ //// [narrowGenericTypeByInstanceOf.ts] -function exampleSingleArgument() { +// From #28560 + +function preserveParentParameters() { class Parent { value: T; } - - class Child extends Parent { - other: T; + class Child extends Parent { + other: S; } - const obj: Parent = undefined as any; - - if (obj instanceof Child) { - obj; - } -} -function exampleSingleExtendsMultiple() { - class Parent { - value1: A; - value2: B; + function withNumber(p: Parent) { + if (p instanceof Child) { + p; + } else { + p; + } } - - class Child extends Parent { - other: T; + function withString(p: Parent) { + if (p instanceof Child) { + p; + } else { + p; + } } - - const obj: Parent = undefined as any; - - if (obj instanceof Child) { - obj; + function withGeneric(p: Parent) { + if (p instanceof Child) { + p; + } else { + p; + } } } -function exampleSwapParameterOrder() { - class Parent { - value1: A; - value2: B; +function copyParameterStructurally() { + class Parent { + value: T; } - - class Child extends Parent { - value3: C; - value4: D; + class Child { + value: S; + other: S; } - const obj: Parent = undefined as any; - - if (obj instanceof Child) { - obj; + function withNumber(p: Parent) { + if (p instanceof Child) { + p; + } else { + p; + } } -} - -function exampleSingleExtendsMultipleReject() { - class Parent { - value1: A; - value2: B; + function withString(p: Parent) { + if (p instanceof Child) { + p; + } else { + p; + } } - - class Child extends Parent { - value3: C; - } - - const obj: Parent = undefined as any; - - if (obj instanceof Child) { - obj; + function withGeneric(p: Parent) { + if (p instanceof Child) { + p; + } else { + p; + } } } -function exampleUnion() { - class Parent { - value1: A; - value2: B; +function useConstraint() { + // #17473 + interface Foo { + foo: string; } - class Child extends Parent { - value3: C; + class Bar { + constructor(readonly bar: T) {} } - const obj0: - | Parent<{ foo: string }, { foo: string }> - | Parent - | Parent = undefined as any; - if (obj0 instanceof Child) { - obj0; + let a: any; + if (a instanceof Bar) { + a.bar; // <-- a.bar should be 'Foo' instead of 'any' } +} - const obj1 = undefined as Parent<{ foo: string }, { foo: string }>; - if (obj1 instanceof Child) { - obj1; +function enhanceConstraint() { + class Parent { + value: T; } - - const obj2 = undefined as Parent; - if (obj2 instanceof Child) { - obj2; + class Child extends Parent { + other: T; } - const obj3 = undefined as Parent; - if (obj3 instanceof Child) { - obj3; + function simpleExtends(p: Parent<1 | 2 | 3 | 4>) { + if (p instanceof Child) { + p; + } else { + p; + } } - - const obj4 = undefined as string | { foo: string }; - if (obj4 instanceof Child) { - obj4; + function complexExtends(p: Parent<2 | 3>) { + if (p instanceof Child) { + p; + } else { + p; + } } - const obj5 = undefined as { foo: string }; - if (obj5 instanceof Child) { - obj5; + function impossibleExtends(p: Parent<3 | 4>) { + if (p instanceof Child) { + p; + } else { + p; + } } } -function exampleNegative() { - class Parent { - value1: A; - value2: B; +function dontWidenPointlessly() { + class Query { + uses: T; } - - class Child extends Parent { - value3: C; + function f(p: T[] | Query) { + if (Array.isArray(p)) { + p; // T[], so far so good + } else if (p instanceof Query) { + p; // should be Query, not Query + } } - - const obj: - | Parent - | Parent - | Child = undefined as any; - - if (obj instanceof Child) { - // Here we filter out matching ones, instead of just narrowing to them. - obj; - return; - } - - console.log(obj); } -function exampleIgnoreDefaults() { - // default parameters shouldn't have any impact on this narrowing. - class Parent { +function multipleParameters() { + class Parent { a: A; + b: B; } - class Child extends Parent { - a2: A2; - c: C; + class Swapped extends Parent { + x: X; + y: Y; } - - const obj: Parent = undefined as any; - if (obj instanceof Child) { - obj; + function checkSwapped(p: Parent) { + if (p instanceof Swapped) { + p; + } else { + p; + } } } -function exampleConstraints() { - class Parent { +function inconsistentParameters() { + class Parent { a: A; - } - class Child extends Parent { b: B; } - - const objPass: Parent<1 | 2 | 3> = undefined as any; - if (objPass instanceof Child) { - objPass; // expect: Child<1 | 2 | 3> - } - - const obj12: Parent<1 | 2> = undefined as any; - if (obj12 instanceof Child) { - obj12; // expect: Child<1 | 2> - } - - const objFail: Parent = undefined as any; - if (objFail instanceof Child) { - objFail; // Child, since string and 1|2|3 have no overlap. - } - - const objRefine: Parent = undefined as any; - if (objRefine instanceof Child) { - objRefine; // expect: Child<1 | 2 | 3> + class Child extends Parent { + c: C; } - - const objRefine1234: Parent<1 | 2 | 3 | 4> = undefined as any; - if (objRefine1234 instanceof Child) { - objRefine1234; // expect: Child<1 | 2 | 3> + function possible(p: Parent) { + if (p instanceof Child) { + p; + } else { + p; + } } - - const objOverlap: Parent<2 | 3 | 4 | 5> = undefined as any; - if (objOverlap instanceof Child) { - objOverlap; // ideally, Child<2 | 3>, but actually Child since 2|3|4|5 is not a supertype of 1|2|3. + function impossible(p: Parent) { + if (p instanceof Child) { + p; + } else { + p; + } } } -function exampleUnrelated() { - class Child { +function union() { + class Parent { a: A; - b: B; - foo: number; - } - - const objA = { a: 5 }; - if (objA instanceof Child) { - objA; // Child - } - - const objB = { b: "hello" }; - if (objB instanceof Child) { - objB; // Child } - - const objAB = { a: 5, b: "hello" }; - if (objAB instanceof Child) { - objAB; // Child - } - - const objAX = { a: 5, x: 7 }; - if (objAX instanceof Child) { - objAX; // Child - } - - const objBX = { b: "hello", x: 7 }; - if (objBX instanceof Child) { - objBX; // Child + class Child extends Parent { + b: B; } - - const objABX = { a: 5, b: "hello", x: 7 }; - if (objABX instanceof Child) { - objABX; // Child + function multipleParents( + p: Parent | Parent | Parent + ) { + if (p instanceof Child) { + p; + } else { + p; + } + } + function mixedChildren(p: Parent | Child) { + if (p instanceof Child) { + p; + } else { + p; + } + } + function imcompatibleOptions( + p: Parent | Parent | { foo: boolean } + ) { + if (p instanceof Child) { + p; + } else { + p; + } } } //// [narrowGenericTypeByInstanceOf.js] +// From #28560 var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || @@ -241,7 +216,7 @@ var __extends = (this && this.__extends) || (function () { d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); -function exampleSingleArgument() { +function preserveParentParameters() { var Parent = /** @class */ (function () { function Parent() { } @@ -254,66 +229,80 @@ function exampleSingleArgument() { } return Child; }(Parent)); - var obj = undefined; - if (obj instanceof Child) { - obj; + function withNumber(p) { + if (p instanceof Child) { + p; + } + else { + p; + } } -} -function exampleSingleExtendsMultiple() { - var Parent = /** @class */ (function () { - function Parent() { + function withString(p) { + if (p instanceof Child) { + p; } - return Parent; - }()); - var Child = /** @class */ (function (_super) { - __extends(Child, _super); - function Child() { - return _super !== null && _super.apply(this, arguments) || this; + else { + p; + } + } + function withGeneric(p) { + if (p instanceof Child) { + p; + } + else { + p; } - return Child; - }(Parent)); - var obj = undefined; - if (obj instanceof Child) { - obj; } } -function exampleSwapParameterOrder() { +function copyParameterStructurally() { var Parent = /** @class */ (function () { function Parent() { } return Parent; }()); - var Child = /** @class */ (function (_super) { - __extends(Child, _super); + var Child = /** @class */ (function () { function Child() { - return _super !== null && _super.apply(this, arguments) || this; } return Child; - }(Parent)); - var obj = undefined; - if (obj instanceof Child) { - obj; + }()); + function withNumber(p) { + if (p instanceof Child) { + p; + } + else { + p; + } + } + function withString(p) { + if (p instanceof Child) { + p; + } + else { + p; + } + } + function withGeneric(p) { + if (p instanceof Child) { + p; + } + else { + p; + } } } -function exampleSingleExtendsMultipleReject() { - var Parent = /** @class */ (function () { - function Parent() { +function useConstraint() { + var Bar = /** @class */ (function () { + function Bar(bar) { + this.bar = bar; } - return Parent; + return Bar; }()); - var Child = /** @class */ (function (_super) { - __extends(Child, _super); - function Child() { - return _super !== null && _super.apply(this, arguments) || this; - } - return Child; - }(Parent)); - var obj = undefined; - if (obj instanceof Child) { - obj; + var a; + if (a instanceof Bar) { + a.bar; // <-- a.bar should be 'Foo' instead of 'any' } } -function exampleUnion() { +function enhanceConstraint() { var Parent = /** @class */ (function () { function Parent() { } @@ -326,54 +315,69 @@ function exampleUnion() { } return Child; }(Parent)); - var obj0 = undefined; - if (obj0 instanceof Child) { - obj0; - } - var obj1 = undefined; - if (obj1 instanceof Child) { - obj1; - } - var obj2 = undefined; - if (obj2 instanceof Child) { - obj2; + function simpleExtends(p) { + if (p instanceof Child) { + p; + } + else { + p; + } } - var obj3 = undefined; - if (obj3 instanceof Child) { - obj3; + function complexExtends(p) { + if (p instanceof Child) { + p; + } + else { + p; + } } - var obj4 = undefined; - if (obj4 instanceof Child) { - obj4; + function impossibleExtends(p) { + if (p instanceof Child) { + p; + } + else { + p; + } } - var obj5 = undefined; - if (obj5 instanceof Child) { - obj5; +} +function dontWidenPointlessly() { + var Query = /** @class */ (function () { + function Query() { + } + return Query; + }()); + function f(p) { + if (Array.isArray(p)) { + p; // T[], so far so good + } + else if (p instanceof Query) { + p; // should be Query, not Query + } } } -function exampleNegative() { +function multipleParameters() { var Parent = /** @class */ (function () { function Parent() { } return Parent; }()); - var Child = /** @class */ (function (_super) { - __extends(Child, _super); - function Child() { + var Swapped = /** @class */ (function (_super) { + __extends(Swapped, _super); + function Swapped() { return _super !== null && _super.apply(this, arguments) || this; } - return Child; + return Swapped; }(Parent)); - var obj = undefined; - if (obj instanceof Child) { - // Here we filter out matching ones, instead of just narrowing to them. - obj; - return; + function checkSwapped(p) { + if (p instanceof Swapped) { + p; + } + else { + p; + } } - console.log(obj); } -function exampleIgnoreDefaults() { - // default parameters shouldn't have any impact on this narrowing. +function inconsistentParameters() { var Parent = /** @class */ (function () { function Parent() { } @@ -386,12 +390,24 @@ function exampleIgnoreDefaults() { } return Child; }(Parent)); - var obj = undefined; - if (obj instanceof Child) { - obj; + function possible(p) { + if (p instanceof Child) { + p; + } + else { + p; + } + } + function impossible(p) { + if (p instanceof Child) { + p; + } + else { + p; + } } } -function exampleConstraints() { +function union() { var Parent = /** @class */ (function () { function Parent() { } @@ -404,59 +420,28 @@ function exampleConstraints() { } return Child; }(Parent)); - var objPass = undefined; - if (objPass instanceof Child) { - objPass; // expect: Child<1 | 2 | 3> - } - var obj12 = undefined; - if (obj12 instanceof Child) { - obj12; // expect: Child<1 | 2> - } - var objFail = undefined; - if (objFail instanceof Child) { - objFail; // Child, since string and 1|2|3 have no overlap. - } - var objRefine = undefined; - if (objRefine instanceof Child) { - objRefine; // expect: Child<1 | 2 | 3> - } - var objRefine1234 = undefined; - if (objRefine1234 instanceof Child) { - objRefine1234; // expect: Child<1 | 2 | 3> - } - var objOverlap = undefined; - if (objOverlap instanceof Child) { - objOverlap; // ideally, Child<2 | 3>, but actually Child since 2|3|4|5 is not a supertype of 1|2|3. - } -} -function exampleUnrelated() { - var Child = /** @class */ (function () { - function Child() { + function multipleParents(p) { + if (p instanceof Child) { + p; + } + else { + p; } - return Child; - }()); - var objA = { a: 5 }; - if (objA instanceof Child) { - objA; // Child - } - var objB = { b: "hello" }; - if (objB instanceof Child) { - objB; // Child - } - var objAB = { a: 5, b: "hello" }; - if (objAB instanceof Child) { - objAB; // Child - } - var objAX = { a: 5, x: 7 }; - if (objAX instanceof Child) { - objAX; // Child } - var objBX = { b: "hello", x: 7 }; - if (objBX instanceof Child) { - objBX; // Child + function mixedChildren(p) { + if (p instanceof Child) { + p; + } + else { + p; + } } - var objABX = { a: 5, b: "hello", x: 7 }; - if (objABX instanceof Child) { - objABX; // Child + function imcompatibleOptions(p) { + if (p instanceof Child) { + p; + } + else { + p; + } } } diff --git a/tests/baselines/reference/narrowGenericTypeByInstanceOf.symbols b/tests/baselines/reference/narrowGenericTypeByInstanceOf.symbols index f49bb5ee2d71f..e8226f7bc23d9 100644 --- a/tests/baselines/reference/narrowGenericTypeByInstanceOf.symbols +++ b/tests/baselines/reference/narrowGenericTypeByInstanceOf.symbols @@ -1,591 +1,506 @@ === tests/cases/compiler/narrowGenericTypeByInstanceOf.ts === -function exampleSingleArgument() { ->exampleSingleArgument : Symbol(exampleSingleArgument, Decl(narrowGenericTypeByInstanceOf.ts, 0, 0)) +// From #28560 + +function preserveParentParameters() { +>preserveParentParameters : Symbol(preserveParentParameters, Decl(narrowGenericTypeByInstanceOf.ts, 0, 0)) class Parent { ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 0, 34)) ->T : Symbol(T, Decl(narrowGenericTypeByInstanceOf.ts, 1, 15)) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 2, 37)) +>T : Symbol(T, Decl(narrowGenericTypeByInstanceOf.ts, 3, 15)) value: T; ->value : Symbol(Parent.value, Decl(narrowGenericTypeByInstanceOf.ts, 1, 19)) ->T : Symbol(T, Decl(narrowGenericTypeByInstanceOf.ts, 1, 15)) +>value : Symbol(Parent.value, Decl(narrowGenericTypeByInstanceOf.ts, 3, 19)) +>T : Symbol(T, Decl(narrowGenericTypeByInstanceOf.ts, 3, 15)) } + class Child extends Parent { +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 5, 3)) +>S : Symbol(S, Decl(narrowGenericTypeByInstanceOf.ts, 6, 14)) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 2, 37)) +>S : Symbol(S, Decl(narrowGenericTypeByInstanceOf.ts, 6, 14)) - class Child extends Parent { ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 3, 3)) ->T : Symbol(T, Decl(narrowGenericTypeByInstanceOf.ts, 5, 14)) ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 0, 34)) ->T : Symbol(T, Decl(narrowGenericTypeByInstanceOf.ts, 5, 14)) - - other: T; ->other : Symbol(Child.other, Decl(narrowGenericTypeByInstanceOf.ts, 5, 36)) ->T : Symbol(T, Decl(narrowGenericTypeByInstanceOf.ts, 5, 14)) + other: S; +>other : Symbol(Child.other, Decl(narrowGenericTypeByInstanceOf.ts, 6, 36)) +>S : Symbol(S, Decl(narrowGenericTypeByInstanceOf.ts, 6, 14)) } - const obj: Parent = undefined as any; ->obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 9, 7)) ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 0, 34)) ->undefined : Symbol(undefined) + function withNumber(p: Parent) { +>withNumber : Symbol(withNumber, Decl(narrowGenericTypeByInstanceOf.ts, 8, 3)) +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 10, 22)) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 2, 37)) - if (obj instanceof Child) { ->obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 9, 7)) ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 3, 3)) + if (p instanceof Child) { +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 10, 22)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 5, 3)) - obj; ->obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 9, 7)) - } -} -function exampleSingleExtendsMultiple() { ->exampleSingleExtendsMultiple : Symbol(exampleSingleExtendsMultiple, Decl(narrowGenericTypeByInstanceOf.ts, 14, 1)) - - class Parent { ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 15, 41)) ->A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 16, 15)) ->B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 16, 17)) + p; +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 10, 22)) - value1: A; ->value1 : Symbol(Parent.value1, Decl(narrowGenericTypeByInstanceOf.ts, 16, 22)) ->A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 16, 15)) - - value2: B; ->value2 : Symbol(Parent.value2, Decl(narrowGenericTypeByInstanceOf.ts, 17, 14)) ->B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 16, 17)) + } else { + p; +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 10, 22)) + } } + function withString(p: Parent) { +>withString : Symbol(withString, Decl(narrowGenericTypeByInstanceOf.ts, 16, 3)) +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 17, 22)) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 2, 37)) - class Child extends Parent { ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 19, 3)) ->T : Symbol(T, Decl(narrowGenericTypeByInstanceOf.ts, 21, 14)) ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 15, 41)) ->T : Symbol(T, Decl(narrowGenericTypeByInstanceOf.ts, 21, 14)) ->T : Symbol(T, Decl(narrowGenericTypeByInstanceOf.ts, 21, 14)) + if (p instanceof Child) { +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 17, 22)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 5, 3)) - other: T; ->other : Symbol(Child.other, Decl(narrowGenericTypeByInstanceOf.ts, 21, 39)) ->T : Symbol(T, Decl(narrowGenericTypeByInstanceOf.ts, 21, 14)) + p; +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 17, 22)) + + } else { + p; +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 17, 22)) + } } + function withGeneric(p: Parent) { +>withGeneric : Symbol(withGeneric, Decl(narrowGenericTypeByInstanceOf.ts, 23, 3)) +>A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 24, 23)) +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 24, 26)) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 2, 37)) +>A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 24, 23)) - const obj: Parent = undefined as any; ->obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 25, 7)) ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 15, 41)) ->undefined : Symbol(undefined) + if (p instanceof Child) { +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 24, 26)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 5, 3)) - if (obj instanceof Child) { ->obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 25, 7)) ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 19, 3)) + p; +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 24, 26)) - obj; ->obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 25, 7)) + } else { + p; +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 24, 26)) + } } } -function exampleSwapParameterOrder() { ->exampleSwapParameterOrder : Symbol(exampleSwapParameterOrder, Decl(narrowGenericTypeByInstanceOf.ts, 30, 1)) +function copyParameterStructurally() { +>copyParameterStructurally : Symbol(copyParameterStructurally, Decl(narrowGenericTypeByInstanceOf.ts, 31, 1)) - class Parent { ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 32, 38)) ->A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 33, 15)) ->B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 33, 17)) - - value1: A; ->value1 : Symbol(Parent.value1, Decl(narrowGenericTypeByInstanceOf.ts, 33, 22)) ->A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 33, 15)) + class Parent { +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 33, 38)) +>T : Symbol(T, Decl(narrowGenericTypeByInstanceOf.ts, 34, 15)) - value2: B; ->value2 : Symbol(Parent.value2, Decl(narrowGenericTypeByInstanceOf.ts, 34, 14)) ->B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 33, 17)) + value: T; +>value : Symbol(Parent.value, Decl(narrowGenericTypeByInstanceOf.ts, 34, 19)) +>T : Symbol(T, Decl(narrowGenericTypeByInstanceOf.ts, 34, 15)) } - - class Child extends Parent { + class Child { >Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 36, 3)) ->C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 38, 14)) ->D : Symbol(D, Decl(narrowGenericTypeByInstanceOf.ts, 38, 16)) ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 32, 38)) ->D : Symbol(D, Decl(narrowGenericTypeByInstanceOf.ts, 38, 16)) ->C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 38, 14)) +>S : Symbol(S, Decl(narrowGenericTypeByInstanceOf.ts, 37, 14)) - value3: C; ->value3 : Symbol(Child.value3, Decl(narrowGenericTypeByInstanceOf.ts, 38, 42)) ->C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 38, 14)) + value: S; +>value : Symbol(Child.value, Decl(narrowGenericTypeByInstanceOf.ts, 37, 18)) +>S : Symbol(S, Decl(narrowGenericTypeByInstanceOf.ts, 37, 14)) - value4: D; ->value4 : Symbol(Child.value4, Decl(narrowGenericTypeByInstanceOf.ts, 39, 14)) ->D : Symbol(D, Decl(narrowGenericTypeByInstanceOf.ts, 38, 16)) + other: S; +>other : Symbol(Child.other, Decl(narrowGenericTypeByInstanceOf.ts, 38, 13)) +>S : Symbol(S, Decl(narrowGenericTypeByInstanceOf.ts, 37, 14)) } - const obj: Parent = undefined as any; ->obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 43, 7)) ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 32, 38)) ->undefined : Symbol(undefined) + function withNumber(p: Parent) { +>withNumber : Symbol(withNumber, Decl(narrowGenericTypeByInstanceOf.ts, 40, 3)) +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 42, 22)) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 33, 38)) - if (obj instanceof Child) { ->obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 43, 7)) + if (p instanceof Child) { +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 42, 22)) >Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 36, 3)) - obj; ->obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 43, 7)) - } -} - -function exampleSingleExtendsMultipleReject() { ->exampleSingleExtendsMultipleReject : Symbol(exampleSingleExtendsMultipleReject, Decl(narrowGenericTypeByInstanceOf.ts, 48, 1)) - - class Parent { ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 50, 47)) ->A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 51, 15)) ->B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 51, 17)) + p; +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 42, 22)) - value1: A; ->value1 : Symbol(Parent.value1, Decl(narrowGenericTypeByInstanceOf.ts, 51, 22)) ->A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 51, 15)) - - value2: B; ->value2 : Symbol(Parent.value2, Decl(narrowGenericTypeByInstanceOf.ts, 52, 14)) ->B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 51, 17)) + } else { + p; +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 42, 22)) + } } + function withString(p: Parent) { +>withString : Symbol(withString, Decl(narrowGenericTypeByInstanceOf.ts, 48, 3)) +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 49, 22)) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 33, 38)) - class Child extends Parent { ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 54, 3)) ->C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 56, 14)) ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 50, 47)) ->C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 56, 14)) ->C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 56, 14)) + if (p instanceof Child) { +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 49, 22)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 36, 3)) - value3: C; ->value3 : Symbol(Child.value3, Decl(narrowGenericTypeByInstanceOf.ts, 56, 39)) ->C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 56, 14)) + p; +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 49, 22)) + + } else { + p; +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 49, 22)) + } } + function withGeneric(p: Parent) { +>withGeneric : Symbol(withGeneric, Decl(narrowGenericTypeByInstanceOf.ts, 55, 3)) +>A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 56, 23)) +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 56, 26)) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 33, 38)) +>A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 56, 23)) - const obj: Parent = undefined as any; ->obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 60, 7)) ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 50, 47)) ->undefined : Symbol(undefined) + if (p instanceof Child) { +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 56, 26)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 36, 3)) - if (obj instanceof Child) { ->obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 60, 7)) ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 54, 3)) + p; +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 56, 26)) - obj; ->obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 60, 7)) + } else { + p; +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 56, 26)) + } } } -function exampleUnion() { ->exampleUnion : Symbol(exampleUnion, Decl(narrowGenericTypeByInstanceOf.ts, 65, 1)) +function useConstraint() { +>useConstraint : Symbol(useConstraint, Decl(narrowGenericTypeByInstanceOf.ts, 63, 1)) - class Parent { ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 67, 25)) ->A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 68, 15)) ->B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 68, 17)) + // #17473 + interface Foo { +>Foo : Symbol(Foo, Decl(narrowGenericTypeByInstanceOf.ts, 65, 26)) - value1: A; ->value1 : Symbol(Parent.value1, Decl(narrowGenericTypeByInstanceOf.ts, 68, 22)) ->A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 68, 15)) - - value2: B; ->value2 : Symbol(Parent.value2, Decl(narrowGenericTypeByInstanceOf.ts, 69, 14)) ->B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 68, 17)) + foo: string; +>foo : Symbol(Foo.foo, Decl(narrowGenericTypeByInstanceOf.ts, 67, 17)) } - class Child extends Parent { ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 71, 3)) ->C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 73, 14)) ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 67, 25)) ->C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 73, 14)) ->C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 73, 14)) + class Bar { +>Bar : Symbol(Bar, Decl(narrowGenericTypeByInstanceOf.ts, 69, 3)) +>T : Symbol(T, Decl(narrowGenericTypeByInstanceOf.ts, 71, 12)) +>Foo : Symbol(Foo, Decl(narrowGenericTypeByInstanceOf.ts, 65, 26)) - value3: C; ->value3 : Symbol(Child.value3, Decl(narrowGenericTypeByInstanceOf.ts, 73, 39)) ->C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 73, 14)) + constructor(readonly bar: T) {} +>bar : Symbol(Bar.bar, Decl(narrowGenericTypeByInstanceOf.ts, 72, 16)) +>T : Symbol(T, Decl(narrowGenericTypeByInstanceOf.ts, 71, 12)) } - const obj0: ->obj0 : Symbol(obj0, Decl(narrowGenericTypeByInstanceOf.ts, 77, 7)) - - | Parent<{ foo: string }, { foo: string }> ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 67, 25)) ->foo : Symbol(foo, Decl(narrowGenericTypeByInstanceOf.ts, 78, 14)) ->foo : Symbol(foo, Decl(narrowGenericTypeByInstanceOf.ts, 78, 31)) - - | Parent ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 67, 25)) + let a: any; +>a : Symbol(a, Decl(narrowGenericTypeByInstanceOf.ts, 75, 5)) - | Parent = undefined as any; ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 67, 25)) ->undefined : Symbol(undefined) + if (a instanceof Bar) { +>a : Symbol(a, Decl(narrowGenericTypeByInstanceOf.ts, 75, 5)) +>Bar : Symbol(Bar, Decl(narrowGenericTypeByInstanceOf.ts, 69, 3)) - if (obj0 instanceof Child) { ->obj0 : Symbol(obj0, Decl(narrowGenericTypeByInstanceOf.ts, 77, 7)) ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 71, 3)) - - obj0; ->obj0 : Symbol(obj0, Decl(narrowGenericTypeByInstanceOf.ts, 77, 7)) - } - - const obj1 = undefined as Parent<{ foo: string }, { foo: string }>; ->obj1 : Symbol(obj1, Decl(narrowGenericTypeByInstanceOf.ts, 85, 7)) ->undefined : Symbol(undefined) ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 67, 25)) ->foo : Symbol(foo, Decl(narrowGenericTypeByInstanceOf.ts, 85, 36)) ->foo : Symbol(foo, Decl(narrowGenericTypeByInstanceOf.ts, 85, 53)) - - if (obj1 instanceof Child) { ->obj1 : Symbol(obj1, Decl(narrowGenericTypeByInstanceOf.ts, 85, 7)) ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 71, 3)) - - obj1; ->obj1 : Symbol(obj1, Decl(narrowGenericTypeByInstanceOf.ts, 85, 7)) + a.bar; // <-- a.bar should be 'Foo' instead of 'any' +>a.bar : Symbol(Bar.bar, Decl(narrowGenericTypeByInstanceOf.ts, 72, 16)) +>a : Symbol(a, Decl(narrowGenericTypeByInstanceOf.ts, 75, 5)) +>bar : Symbol(Bar.bar, Decl(narrowGenericTypeByInstanceOf.ts, 72, 16)) } +} - const obj2 = undefined as Parent; ->obj2 : Symbol(obj2, Decl(narrowGenericTypeByInstanceOf.ts, 90, 7)) ->undefined : Symbol(undefined) ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 67, 25)) +function enhanceConstraint() { +>enhanceConstraint : Symbol(enhanceConstraint, Decl(narrowGenericTypeByInstanceOf.ts, 79, 1)) - if (obj2 instanceof Child) { ->obj2 : Symbol(obj2, Decl(narrowGenericTypeByInstanceOf.ts, 90, 7)) ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 71, 3)) + class Parent { +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 81, 30)) +>T : Symbol(T, Decl(narrowGenericTypeByInstanceOf.ts, 82, 15)) - obj2; ->obj2 : Symbol(obj2, Decl(narrowGenericTypeByInstanceOf.ts, 90, 7)) + value: T; +>value : Symbol(Parent.value, Decl(narrowGenericTypeByInstanceOf.ts, 82, 41)) +>T : Symbol(T, Decl(narrowGenericTypeByInstanceOf.ts, 82, 15)) } + class Child extends Parent { +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 84, 3)) +>T : Symbol(T, Decl(narrowGenericTypeByInstanceOf.ts, 85, 14)) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 81, 30)) +>T : Symbol(T, Decl(narrowGenericTypeByInstanceOf.ts, 85, 14)) - const obj3 = undefined as Parent; ->obj3 : Symbol(obj3, Decl(narrowGenericTypeByInstanceOf.ts, 95, 7)) ->undefined : Symbol(undefined) ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 67, 25)) - - if (obj3 instanceof Child) { ->obj3 : Symbol(obj3, Decl(narrowGenericTypeByInstanceOf.ts, 95, 7)) ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 71, 3)) - - obj3; ->obj3 : Symbol(obj3, Decl(narrowGenericTypeByInstanceOf.ts, 95, 7)) + other: T; +>other : Symbol(Child.other, Decl(narrowGenericTypeByInstanceOf.ts, 85, 50)) +>T : Symbol(T, Decl(narrowGenericTypeByInstanceOf.ts, 85, 14)) } - const obj4 = undefined as string | { foo: string }; ->obj4 : Symbol(obj4, Decl(narrowGenericTypeByInstanceOf.ts, 100, 7)) ->undefined : Symbol(undefined) ->foo : Symbol(foo, Decl(narrowGenericTypeByInstanceOf.ts, 100, 38)) - - if (obj4 instanceof Child) { ->obj4 : Symbol(obj4, Decl(narrowGenericTypeByInstanceOf.ts, 100, 7)) ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 71, 3)) + function simpleExtends(p: Parent<1 | 2 | 3 | 4>) { +>simpleExtends : Symbol(simpleExtends, Decl(narrowGenericTypeByInstanceOf.ts, 87, 3)) +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 89, 25)) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 81, 30)) - obj4; ->obj4 : Symbol(obj4, Decl(narrowGenericTypeByInstanceOf.ts, 100, 7)) - } - const obj5 = undefined as { foo: string }; ->obj5 : Symbol(obj5, Decl(narrowGenericTypeByInstanceOf.ts, 104, 7)) ->undefined : Symbol(undefined) ->foo : Symbol(foo, Decl(narrowGenericTypeByInstanceOf.ts, 104, 29)) + if (p instanceof Child) { +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 89, 25)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 84, 3)) - if (obj5 instanceof Child) { ->obj5 : Symbol(obj5, Decl(narrowGenericTypeByInstanceOf.ts, 104, 7)) ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 71, 3)) + p; +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 89, 25)) - obj5; ->obj5 : Symbol(obj5, Decl(narrowGenericTypeByInstanceOf.ts, 104, 7)) + } else { + p; +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 89, 25)) + } } -} - -function exampleNegative() { ->exampleNegative : Symbol(exampleNegative, Decl(narrowGenericTypeByInstanceOf.ts, 108, 1)) - - class Parent { ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 110, 28)) ->A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 111, 15)) ->B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 111, 17)) - - value1: A; ->value1 : Symbol(Parent.value1, Decl(narrowGenericTypeByInstanceOf.ts, 111, 22)) ->A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 111, 15)) + function complexExtends(p: Parent<2 | 3>) { +>complexExtends : Symbol(complexExtends, Decl(narrowGenericTypeByInstanceOf.ts, 95, 3)) +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 96, 26)) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 81, 30)) - value2: B; ->value2 : Symbol(Parent.value2, Decl(narrowGenericTypeByInstanceOf.ts, 112, 14)) ->B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 111, 17)) - } + if (p instanceof Child) { +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 96, 26)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 84, 3)) - class Child extends Parent { ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 114, 3)) ->C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 116, 14)) ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 110, 28)) ->C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 116, 14)) ->C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 116, 14)) + p; +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 96, 26)) - value3: C; ->value3 : Symbol(Child.value3, Decl(narrowGenericTypeByInstanceOf.ts, 116, 39)) ->C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 116, 14)) + } else { + p; +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 96, 26)) + } } + function impossibleExtends(p: Parent<3 | 4>) { +>impossibleExtends : Symbol(impossibleExtends, Decl(narrowGenericTypeByInstanceOf.ts, 102, 3)) +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 103, 29)) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 81, 30)) - const obj: ->obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 120, 7)) - - | Parent ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 110, 28)) - - | Parent ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 110, 28)) + if (p instanceof Child) { +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 103, 29)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 84, 3)) - | Child = undefined as any; ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 114, 3)) ->undefined : Symbol(undefined) + p; +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 103, 29)) - if (obj instanceof Child) { ->obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 120, 7)) ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 114, 3)) - - // Here we filter out matching ones, instead of just narrowing to them. - obj; ->obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 120, 7)) - - return; + } else { + p; +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 103, 29)) + } } - - console.log(obj); ->console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) ->console : Symbol(console, Decl(lib.dom.d.ts, --, --)) ->log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) ->obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 120, 7)) } -function exampleIgnoreDefaults() { ->exampleIgnoreDefaults : Symbol(exampleIgnoreDefaults, Decl(narrowGenericTypeByInstanceOf.ts, 132, 1)) +function dontWidenPointlessly() { +>dontWidenPointlessly : Symbol(dontWidenPointlessly, Decl(narrowGenericTypeByInstanceOf.ts, 110, 1)) - // default parameters shouldn't have any impact on this narrowing. - class Parent { ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 134, 34)) ->A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 136, 15)) + class Query { +>Query : Symbol(Query, Decl(narrowGenericTypeByInstanceOf.ts, 112, 33)) +>T : Symbol(T, Decl(narrowGenericTypeByInstanceOf.ts, 113, 14)) - a: A; ->a : Symbol(Parent.a, Decl(narrowGenericTypeByInstanceOf.ts, 136, 19)) ->A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 136, 15)) + uses: T; +>uses : Symbol(Query.uses, Decl(narrowGenericTypeByInstanceOf.ts, 113, 18)) +>T : Symbol(T, Decl(narrowGenericTypeByInstanceOf.ts, 113, 14)) } - class Child extends Parent { ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 138, 3)) ->A2 : Symbol(A2, Decl(narrowGenericTypeByInstanceOf.ts, 139, 14)) ->C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 139, 17)) ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 134, 34)) ->A2 : Symbol(A2, Decl(narrowGenericTypeByInstanceOf.ts, 139, 14)) + function f(p: T[] | Query) { +>f : Symbol(f, Decl(narrowGenericTypeByInstanceOf.ts, 115, 3)) +>T : Symbol(T, Decl(narrowGenericTypeByInstanceOf.ts, 116, 13)) +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 116, 16)) +>T : Symbol(T, Decl(narrowGenericTypeByInstanceOf.ts, 116, 13)) +>Query : Symbol(Query, Decl(narrowGenericTypeByInstanceOf.ts, 112, 33)) +>T : Symbol(T, Decl(narrowGenericTypeByInstanceOf.ts, 116, 13)) - a2: A2; ->a2 : Symbol(Child.a2, Decl(narrowGenericTypeByInstanceOf.ts, 139, 50)) ->A2 : Symbol(A2, Decl(narrowGenericTypeByInstanceOf.ts, 139, 14)) + if (Array.isArray(p)) { +>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 116, 16)) - c: C; ->c : Symbol(Child.c, Decl(narrowGenericTypeByInstanceOf.ts, 140, 11)) ->C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 139, 17)) - } + p; // T[], so far so good +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 116, 16)) - const obj: Parent = undefined as any; ->obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 144, 7)) ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 134, 34)) ->undefined : Symbol(undefined) + } else if (p instanceof Query) { +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 116, 16)) +>Query : Symbol(Query, Decl(narrowGenericTypeByInstanceOf.ts, 112, 33)) - if (obj instanceof Child) { ->obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 144, 7)) ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 138, 3)) - - obj; ->obj : Symbol(obj, Decl(narrowGenericTypeByInstanceOf.ts, 144, 7)) + p; // should be Query, not Query +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 116, 16)) + } } } -function exampleConstraints() { ->exampleConstraints : Symbol(exampleConstraints, Decl(narrowGenericTypeByInstanceOf.ts, 148, 1)) +function multipleParameters() { +>multipleParameters : Symbol(multipleParameters, Decl(narrowGenericTypeByInstanceOf.ts, 123, 1)) - class Parent { ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 150, 31)) ->A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 151, 15)) + class Parent { +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 125, 31)) +>A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 126, 15)) +>B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 126, 17)) a: A; ->a : Symbol(Parent.a, Decl(narrowGenericTypeByInstanceOf.ts, 151, 19)) ->A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 151, 15)) - } - class Child extends Parent { ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 153, 3)) ->B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 154, 14)) ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 150, 31)) ->B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 154, 14)) +>a : Symbol(Parent.a, Decl(narrowGenericTypeByInstanceOf.ts, 126, 22)) +>A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 126, 15)) b: B; ->b : Symbol(Child.b, Decl(narrowGenericTypeByInstanceOf.ts, 154, 54)) ->B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 154, 14)) - } - - const objPass: Parent<1 | 2 | 3> = undefined as any; ->objPass : Symbol(objPass, Decl(narrowGenericTypeByInstanceOf.ts, 158, 7)) ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 150, 31)) ->undefined : Symbol(undefined) - - if (objPass instanceof Child) { ->objPass : Symbol(objPass, Decl(narrowGenericTypeByInstanceOf.ts, 158, 7)) ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 153, 3)) - - objPass; // expect: Child<1 | 2 | 3> ->objPass : Symbol(objPass, Decl(narrowGenericTypeByInstanceOf.ts, 158, 7)) - } - - const obj12: Parent<1 | 2> = undefined as any; ->obj12 : Symbol(obj12, Decl(narrowGenericTypeByInstanceOf.ts, 163, 7)) ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 150, 31)) ->undefined : Symbol(undefined) - - if (obj12 instanceof Child) { ->obj12 : Symbol(obj12, Decl(narrowGenericTypeByInstanceOf.ts, 163, 7)) ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 153, 3)) - - obj12; // expect: Child<1 | 2> ->obj12 : Symbol(obj12, Decl(narrowGenericTypeByInstanceOf.ts, 163, 7)) - } - - const objFail: Parent = undefined as any; ->objFail : Symbol(objFail, Decl(narrowGenericTypeByInstanceOf.ts, 168, 7)) ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 150, 31)) ->undefined : Symbol(undefined) - - if (objFail instanceof Child) { ->objFail : Symbol(objFail, Decl(narrowGenericTypeByInstanceOf.ts, 168, 7)) ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 153, 3)) - - objFail; // Child, since string and 1|2|3 have no overlap. ->objFail : Symbol(objFail, Decl(narrowGenericTypeByInstanceOf.ts, 168, 7)) - } - - const objRefine: Parent = undefined as any; ->objRefine : Symbol(objRefine, Decl(narrowGenericTypeByInstanceOf.ts, 173, 7)) ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 150, 31)) ->undefined : Symbol(undefined) - - if (objRefine instanceof Child) { ->objRefine : Symbol(objRefine, Decl(narrowGenericTypeByInstanceOf.ts, 173, 7)) ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 153, 3)) - - objRefine; // expect: Child<1 | 2 | 3> ->objRefine : Symbol(objRefine, Decl(narrowGenericTypeByInstanceOf.ts, 173, 7)) - } - - const objRefine1234: Parent<1 | 2 | 3 | 4> = undefined as any; ->objRefine1234 : Symbol(objRefine1234, Decl(narrowGenericTypeByInstanceOf.ts, 178, 7)) ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 150, 31)) ->undefined : Symbol(undefined) - - if (objRefine1234 instanceof Child) { ->objRefine1234 : Symbol(objRefine1234, Decl(narrowGenericTypeByInstanceOf.ts, 178, 7)) ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 153, 3)) - - objRefine1234; // expect: Child<1 | 2 | 3> ->objRefine1234 : Symbol(objRefine1234, Decl(narrowGenericTypeByInstanceOf.ts, 178, 7)) - } - - const objOverlap: Parent<2 | 3 | 4 | 5> = undefined as any; ->objOverlap : Symbol(objOverlap, Decl(narrowGenericTypeByInstanceOf.ts, 183, 7)) ->Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 150, 31)) ->undefined : Symbol(undefined) - - if (objOverlap instanceof Child) { ->objOverlap : Symbol(objOverlap, Decl(narrowGenericTypeByInstanceOf.ts, 183, 7)) ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 153, 3)) - - objOverlap; // ideally, Child<2 | 3>, but actually Child since 2|3|4|5 is not a supertype of 1|2|3. ->objOverlap : Symbol(objOverlap, Decl(narrowGenericTypeByInstanceOf.ts, 183, 7)) +>b : Symbol(Parent.b, Decl(narrowGenericTypeByInstanceOf.ts, 127, 9)) +>B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 126, 17)) + } + class Swapped extends Parent { +>Swapped : Symbol(Swapped, Decl(narrowGenericTypeByInstanceOf.ts, 129, 3)) +>X : Symbol(X, Decl(narrowGenericTypeByInstanceOf.ts, 130, 16)) +>Y : Symbol(Y, Decl(narrowGenericTypeByInstanceOf.ts, 130, 18)) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 125, 31)) +>Y : Symbol(Y, Decl(narrowGenericTypeByInstanceOf.ts, 130, 18)) +>X : Symbol(X, Decl(narrowGenericTypeByInstanceOf.ts, 130, 16)) + + x: X; +>x : Symbol(Swapped.x, Decl(narrowGenericTypeByInstanceOf.ts, 130, 44)) +>X : Symbol(X, Decl(narrowGenericTypeByInstanceOf.ts, 130, 16)) + + y: Y; +>y : Symbol(Swapped.y, Decl(narrowGenericTypeByInstanceOf.ts, 131, 9)) +>Y : Symbol(Y, Decl(narrowGenericTypeByInstanceOf.ts, 130, 18)) + } + function checkSwapped(p: Parent) { +>checkSwapped : Symbol(checkSwapped, Decl(narrowGenericTypeByInstanceOf.ts, 133, 3)) +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 134, 24)) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 125, 31)) + + if (p instanceof Swapped) { +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 134, 24)) +>Swapped : Symbol(Swapped, Decl(narrowGenericTypeByInstanceOf.ts, 129, 3)) + + p; +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 134, 24)) + + } else { + p; +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 134, 24)) + } } } -function exampleUnrelated() { ->exampleUnrelated : Symbol(exampleUnrelated, Decl(narrowGenericTypeByInstanceOf.ts, 187, 1)) +function inconsistentParameters() { +>inconsistentParameters : Symbol(inconsistentParameters, Decl(narrowGenericTypeByInstanceOf.ts, 141, 1)) - class Child { ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 189, 29)) ->A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 190, 14)) ->B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 190, 16)) + class Parent { +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 143, 35)) +>A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 144, 15)) +>B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 144, 17)) a: A; ->a : Symbol(Child.a, Decl(narrowGenericTypeByInstanceOf.ts, 190, 21)) ->A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 190, 14)) +>a : Symbol(Parent.a, Decl(narrowGenericTypeByInstanceOf.ts, 144, 22)) +>A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 144, 15)) b: B; ->b : Symbol(Child.b, Decl(narrowGenericTypeByInstanceOf.ts, 191, 9)) ->B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 190, 16)) - - foo: number; ->foo : Symbol(Child.foo, Decl(narrowGenericTypeByInstanceOf.ts, 192, 9)) +>b : Symbol(Parent.b, Decl(narrowGenericTypeByInstanceOf.ts, 145, 9)) +>B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 144, 17)) } + class Child extends Parent { +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 147, 3)) +>C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 148, 14)) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 143, 35)) +>C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 148, 14)) +>C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 148, 14)) - const objA = { a: 5 }; ->objA : Symbol(objA, Decl(narrowGenericTypeByInstanceOf.ts, 196, 7)) ->a : Symbol(a, Decl(narrowGenericTypeByInstanceOf.ts, 196, 16)) - - if (objA instanceof Child) { ->objA : Symbol(objA, Decl(narrowGenericTypeByInstanceOf.ts, 196, 7)) ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 189, 29)) - - objA; // Child ->objA : Symbol(objA, Decl(narrowGenericTypeByInstanceOf.ts, 196, 7)) - } - - const objB = { b: "hello" }; ->objB : Symbol(objB, Decl(narrowGenericTypeByInstanceOf.ts, 201, 7)) ->b : Symbol(b, Decl(narrowGenericTypeByInstanceOf.ts, 201, 16)) - - if (objB instanceof Child) { ->objB : Symbol(objB, Decl(narrowGenericTypeByInstanceOf.ts, 201, 7)) ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 189, 29)) - - objB; // Child ->objB : Symbol(objB, Decl(narrowGenericTypeByInstanceOf.ts, 201, 7)) + c: C; +>c : Symbol(Child.c, Decl(narrowGenericTypeByInstanceOf.ts, 148, 39)) +>C : Symbol(C, Decl(narrowGenericTypeByInstanceOf.ts, 148, 14)) } + function possible(p: Parent) { +>possible : Symbol(possible, Decl(narrowGenericTypeByInstanceOf.ts, 150, 3)) +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 151, 20)) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 143, 35)) - const objAB = { a: 5, b: "hello" }; ->objAB : Symbol(objAB, Decl(narrowGenericTypeByInstanceOf.ts, 206, 7)) ->a : Symbol(a, Decl(narrowGenericTypeByInstanceOf.ts, 206, 17)) ->b : Symbol(b, Decl(narrowGenericTypeByInstanceOf.ts, 206, 23)) + if (p instanceof Child) { +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 151, 20)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 147, 3)) - if (objAB instanceof Child) { ->objAB : Symbol(objAB, Decl(narrowGenericTypeByInstanceOf.ts, 206, 7)) ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 189, 29)) + p; +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 151, 20)) - objAB; // Child ->objAB : Symbol(objAB, Decl(narrowGenericTypeByInstanceOf.ts, 206, 7)) + } else { + p; +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 151, 20)) + } } + function impossible(p: Parent) { +>impossible : Symbol(impossible, Decl(narrowGenericTypeByInstanceOf.ts, 157, 3)) +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 158, 22)) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 143, 35)) - const objAX = { a: 5, x: 7 }; ->objAX : Symbol(objAX, Decl(narrowGenericTypeByInstanceOf.ts, 211, 7)) ->a : Symbol(a, Decl(narrowGenericTypeByInstanceOf.ts, 211, 17)) ->x : Symbol(x, Decl(narrowGenericTypeByInstanceOf.ts, 211, 23)) + if (p instanceof Child) { +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 158, 22)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 147, 3)) - if (objAX instanceof Child) { ->objAX : Symbol(objAX, Decl(narrowGenericTypeByInstanceOf.ts, 211, 7)) ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 189, 29)) + p; +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 158, 22)) - objAX; // Child ->objAX : Symbol(objAX, Decl(narrowGenericTypeByInstanceOf.ts, 211, 7)) + } else { + p; +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 158, 22)) + } } +} - const objBX = { b: "hello", x: 7 }; ->objBX : Symbol(objBX, Decl(narrowGenericTypeByInstanceOf.ts, 216, 7)) ->b : Symbol(b, Decl(narrowGenericTypeByInstanceOf.ts, 216, 17)) ->x : Symbol(x, Decl(narrowGenericTypeByInstanceOf.ts, 216, 29)) +function union() { +>union : Symbol(union, Decl(narrowGenericTypeByInstanceOf.ts, 165, 1)) - if (objBX instanceof Child) { ->objBX : Symbol(objBX, Decl(narrowGenericTypeByInstanceOf.ts, 216, 7)) ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 189, 29)) + class Parent { +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 167, 18)) +>A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 168, 15)) - objBX; // Child ->objBX : Symbol(objBX, Decl(narrowGenericTypeByInstanceOf.ts, 216, 7)) + a: A; +>a : Symbol(Parent.a, Decl(narrowGenericTypeByInstanceOf.ts, 168, 19)) +>A : Symbol(A, Decl(narrowGenericTypeByInstanceOf.ts, 168, 15)) } + class Child extends Parent { +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 170, 3)) +>B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 171, 14)) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 167, 18)) +>B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 171, 14)) - const objABX = { a: 5, b: "hello", x: 7 }; ->objABX : Symbol(objABX, Decl(narrowGenericTypeByInstanceOf.ts, 221, 7)) ->a : Symbol(a, Decl(narrowGenericTypeByInstanceOf.ts, 221, 18)) ->b : Symbol(b, Decl(narrowGenericTypeByInstanceOf.ts, 221, 24)) ->x : Symbol(x, Decl(narrowGenericTypeByInstanceOf.ts, 221, 36)) - - if (objABX instanceof Child) { ->objABX : Symbol(objABX, Decl(narrowGenericTypeByInstanceOf.ts, 221, 7)) ->Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 189, 29)) - - objABX; // Child ->objABX : Symbol(objABX, Decl(narrowGenericTypeByInstanceOf.ts, 221, 7)) + b: B; +>b : Symbol(Child.b, Decl(narrowGenericTypeByInstanceOf.ts, 171, 36)) +>B : Symbol(B, Decl(narrowGenericTypeByInstanceOf.ts, 171, 14)) + } + function multipleParents( +>multipleParents : Symbol(multipleParents, Decl(narrowGenericTypeByInstanceOf.ts, 173, 3)) + + p: Parent | Parent | Parent +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 174, 27)) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 167, 18)) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 167, 18)) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 167, 18)) + + ) { + if (p instanceof Child) { +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 174, 27)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 170, 3)) + + p; +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 174, 27)) + + } else { + p; +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 174, 27)) + } + } + function mixedChildren(p: Parent | Child) { +>mixedChildren : Symbol(mixedChildren, Decl(narrowGenericTypeByInstanceOf.ts, 182, 3)) +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 183, 25)) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 167, 18)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 170, 3)) + + if (p instanceof Child) { +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 183, 25)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 170, 3)) + + p; +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 183, 25)) + + } else { + p; +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 183, 25)) + } + } + function imcompatibleOptions( +>imcompatibleOptions : Symbol(imcompatibleOptions, Decl(narrowGenericTypeByInstanceOf.ts, 189, 3)) + + p: Parent | Parent | { foo: boolean } +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 190, 31)) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 167, 18)) +>Parent : Symbol(Parent, Decl(narrowGenericTypeByInstanceOf.ts, 167, 18)) +>foo : Symbol(foo, Decl(narrowGenericTypeByInstanceOf.ts, 191, 42)) + + ) { + if (p instanceof Child) { +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 190, 31)) +>Child : Symbol(Child, Decl(narrowGenericTypeByInstanceOf.ts, 170, 3)) + + p; +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 190, 31)) + + } else { + p; +>p : Symbol(p, Decl(narrowGenericTypeByInstanceOf.ts, 190, 31)) + } } } diff --git a/tests/baselines/reference/narrowGenericTypeByInstanceOf.types b/tests/baselines/reference/narrowGenericTypeByInstanceOf.types index 0c2884234ca60..c6008bf320c16 100644 --- a/tests/baselines/reference/narrowGenericTypeByInstanceOf.types +++ b/tests/baselines/reference/narrowGenericTypeByInstanceOf.types @@ -1,6 +1,8 @@ === tests/cases/compiler/narrowGenericTypeByInstanceOf.ts === -function exampleSingleArgument() { ->exampleSingleArgument : () => void +// From #28560 + +function preserveParentParameters() { +>preserveParentParameters : () => void class Parent { >Parent : Parent @@ -8,558 +10,443 @@ function exampleSingleArgument() { value: T; >value : T } + class Child extends Parent { +>Child : Child +>Parent : Parent - class Child extends Parent { ->Child : Child ->Parent : Parent - - other: T; ->other : T + other: S; +>other : S } - const obj: Parent = undefined as any; ->obj : Parent ->undefined as any : any ->undefined : undefined + function withNumber(p: Parent) { +>withNumber : (p: Parent) => void +>p : Parent - if (obj instanceof Child) { ->obj instanceof Child : boolean ->obj : Parent + if (p instanceof Child) { +>p instanceof Child : boolean +>p : Parent >Child : typeof Child - obj; ->obj : Child - } -} -function exampleSingleExtendsMultiple() { ->exampleSingleExtendsMultiple : () => void + p; +>p : Child - class Parent { ->Parent : Parent - - value1: A; ->value1 : A - - value2: B; ->value2 : B + } else { + p; +>p : Parent + } } + function withString(p: Parent) { +>withString : (p: Parent) => void +>p : Parent - class Child extends Parent { ->Child : Child ->Parent : Parent + if (p instanceof Child) { +>p instanceof Child : boolean +>p : Parent +>Child : typeof Child - other: T; ->other : T - } + p; +>p : Child - const obj: Parent = undefined as any; ->obj : Parent ->undefined as any : any ->undefined : undefined + } else { + p; +>p : Parent + } + } + function withGeneric(p: Parent) { +>withGeneric : (p: Parent) => void +>p : Parent - if (obj instanceof Child) { ->obj instanceof Child : boolean ->obj : Parent + if (p instanceof Child) { +>p instanceof Child : boolean +>p : Parent >Child : typeof Child - obj; ->obj : Child + p; +>p : Child + + } else { + p; +>p : Parent + } } } -function exampleSwapParameterOrder() { ->exampleSwapParameterOrder : () => void +function copyParameterStructurally() { +>copyParameterStructurally : () => void - class Parent { ->Parent : Parent - - value1: A; ->value1 : A + class Parent { +>Parent : Parent - value2: B; ->value2 : B + value: T; +>value : T } + class Child { +>Child : Child - class Child extends Parent { ->Child : Child ->Parent : Parent + value: S; +>value : S - value3: C; ->value3 : C - - value4: D; ->value4 : D + other: S; +>other : S } - const obj: Parent = undefined as any; ->obj : Parent ->undefined as any : any ->undefined : undefined + function withNumber(p: Parent) { +>withNumber : (p: Parent) => void +>p : Parent - if (obj instanceof Child) { ->obj instanceof Child : boolean ->obj : Parent + if (p instanceof Child) { +>p instanceof Child : boolean +>p : Parent >Child : typeof Child - obj; ->obj : Child - } -} - -function exampleSingleExtendsMultipleReject() { ->exampleSingleExtendsMultipleReject : () => void - - class Parent { ->Parent : Parent + p; +>p : Child - value1: A; ->value1 : A - - value2: B; ->value2 : B + } else { + p; +>p : Parent + } } + function withString(p: Parent) { +>withString : (p: Parent) => void +>p : Parent - class Child extends Parent { ->Child : Child ->Parent : Parent + if (p instanceof Child) { +>p instanceof Child : boolean +>p : Parent +>Child : typeof Child - value3: C; ->value3 : C - } + p; +>p : Child - const obj: Parent = undefined as any; ->obj : Parent ->undefined as any : any ->undefined : undefined + } else { + p; +>p : Parent + } + } + function withGeneric(p: Parent) { +>withGeneric : (p: Parent) => void +>p : Parent - if (obj instanceof Child) { ->obj instanceof Child : boolean ->obj : Parent + if (p instanceof Child) { +>p instanceof Child : boolean +>p : Parent >Child : typeof Child - obj; ->obj : Child + p; +>p : Child + + } else { + p; +>p : Parent + } } } -function exampleUnion() { ->exampleUnion : () => void +function useConstraint() { +>useConstraint : () => void - class Parent { ->Parent : Parent - - value1: A; ->value1 : A - - value2: B; ->value2 : B + // #17473 + interface Foo { + foo: string; +>foo : string } - class Child extends Parent { ->Child : Child ->Parent : Parent + class Bar { +>Bar : Bar - value3: C; ->value3 : C + constructor(readonly bar: T) {} +>bar : T } - const obj0: ->obj0 : Parent<{ foo: string; }, { foo: string; }> | Parent | Parent + let a: any; +>a : any - | Parent<{ foo: string }, { foo: string }> ->foo : string ->foo : string + if (a instanceof Bar) { +>a instanceof Bar : boolean +>a : any +>Bar : typeof Bar - | Parent - | Parent = undefined as any; ->undefined as any : any ->undefined : undefined - - if (obj0 instanceof Child) { ->obj0 instanceof Child : boolean ->obj0 : Parent<{ foo: string; }, { foo: string; }> | Parent | Parent ->Child : typeof Child - - obj0; ->obj0 : Child<{ foo: string; }> | Child | Child + a.bar; // <-- a.bar should be 'Foo' instead of 'any' +>a.bar : any +>a : Bar +>bar : any } +} - const obj1 = undefined as Parent<{ foo: string }, { foo: string }>; ->obj1 : Parent<{ foo: string; }, { foo: string; }> ->undefined as Parent<{ foo: string }, { foo: string }> : Parent<{ foo: string; }, { foo: string; }> ->undefined : undefined ->foo : string ->foo : string +function enhanceConstraint() { +>enhanceConstraint : () => void - if (obj1 instanceof Child) { ->obj1 instanceof Child : boolean ->obj1 : Parent<{ foo: string; }, { foo: string; }> ->Child : typeof Child + class Parent { +>Parent : Parent - obj1; ->obj1 : Child<{ foo: string; }> + value: T; +>value : T } + class Child extends Parent { +>Child : Child +>Parent : Parent - const obj2 = undefined as Parent; ->obj2 : Parent ->undefined as Parent : Parent ->undefined : undefined - - if (obj2 instanceof Child) { ->obj2 instanceof Child : boolean ->obj2 : Parent ->Child : typeof Child - - obj2; ->obj2 : Child + other: T; +>other : T } - const obj3 = undefined as Parent; ->obj3 : Parent ->undefined as Parent : Parent ->undefined : undefined + function simpleExtends(p: Parent<1 | 2 | 3 | 4>) { +>simpleExtends : (p: Parent<1 | 2 | 3 | 4>) => void +>p : Parent<1 | 2 | 3 | 4> - if (obj3 instanceof Child) { ->obj3 instanceof Child : boolean ->obj3 : Parent + if (p instanceof Child) { +>p instanceof Child : boolean +>p : Parent<1 | 2 | 3 | 4> >Child : typeof Child - obj3; ->obj3 : Child - } + p; +>p : Child<1 | 2> - const obj4 = undefined as string | { foo: string }; ->obj4 : string | { foo: string; } ->undefined as string | { foo: string } : string | { foo: string; } ->undefined : undefined ->foo : string + } else { + p; +>p : Parent<1 | 2 | 3 | 4> + } + } + function complexExtends(p: Parent<2 | 3>) { +>complexExtends : (p: Parent<2 | 3>) => void +>p : Parent<2 | 3> - if (obj4 instanceof Child) { ->obj4 instanceof Child : boolean ->obj4 : string | { foo: string; } + if (p instanceof Child) { +>p instanceof Child : boolean +>p : Parent<2 | 3> >Child : typeof Child - obj4; ->obj4 : (string & Child) | ({ foo: string; } & Child) + p; +>p : Child + + } else { + p; +>p : Parent<2 | 3> + } } - const obj5 = undefined as { foo: string }; ->obj5 : { foo: string; } ->undefined as { foo: string } : { foo: string; } ->undefined : undefined ->foo : string + function impossibleExtends(p: Parent<3 | 4>) { +>impossibleExtends : (p: Parent<3 | 4>) => void +>p : Parent<3 | 4> - if (obj5 instanceof Child) { ->obj5 instanceof Child : boolean ->obj5 : { foo: string; } + if (p instanceof Child) { +>p instanceof Child : boolean +>p : Parent<3 | 4> >Child : typeof Child - obj5; ->obj5 : { foo: string; } & Child + p; +>p : Child + + } else { + p; +>p : Parent<3 | 4> + } } } -function exampleNegative() { ->exampleNegative : () => void - - class Parent { ->Parent : Parent - - value1: A; ->value1 : A +function dontWidenPointlessly() { +>dontWidenPointlessly : () => void - value2: B; ->value2 : B - } - - class Child extends Parent { ->Child : Child ->Parent : Parent + class Query { +>Query : Query - value3: C; ->value3 : C + uses: T; +>uses : T } + function f(p: T[] | Query) { +>f : (p: Query | T[]) => void +>p : Query | T[] - const obj: ->obj : Parent | Parent | Child - - | Parent - | Parent - | Child = undefined as any; ->undefined as any : any ->undefined : undefined + if (Array.isArray(p)) { +>Array.isArray(p) : boolean +>Array.isArray : (arg: any) => arg is any[] +>Array : ArrayConstructor +>isArray : (arg: any) => arg is any[] +>p : Query | T[] - if (obj instanceof Child) { ->obj instanceof Child : boolean ->obj : Parent | Parent | Child ->Child : typeof Child + p; // T[], so far so good +>p : T[] - // Here we filter out matching ones, instead of just narrowing to them. - obj; ->obj : Child + } else if (p instanceof Query) { +>p instanceof Query : boolean +>p : Query +>Query : typeof Query - return; + p; // should be Query, not Query +>p : Query + } } - - console.log(obj); ->console.log(obj) : void ->console.log : (message?: any, ...optionalParams: any[]) => void ->console : Console ->log : (message?: any, ...optionalParams: any[]) => void ->obj : Parent | Parent } -function exampleIgnoreDefaults() { ->exampleIgnoreDefaults : () => void +function multipleParameters() { +>multipleParameters : () => void - // default parameters shouldn't have any impact on this narrowing. - class Parent { ->Parent : Parent + class Parent { +>Parent : Parent a: A; >a : A + + b: B; +>b : B } - class Child extends Parent { ->Child : Child ->Parent : Parent + class Swapped extends Parent { +>Swapped : Swapped +>Parent : Parent - a2: A2; ->a2 : A2 + x: X; +>x : X - c: C; ->c : C + y: Y; +>y : Y } + function checkSwapped(p: Parent) { +>checkSwapped : (p: Parent) => void +>p : Parent - const obj: Parent = undefined as any; ->obj : Parent ->undefined as any : any ->undefined : undefined + if (p instanceof Swapped) { +>p instanceof Swapped : boolean +>p : Parent +>Swapped : typeof Swapped - if (obj instanceof Child) { ->obj instanceof Child : boolean ->obj : Parent ->Child : typeof Child + p; +>p : Swapped - obj; ->obj : Child + } else { + p; +>p : Parent + } } } -function exampleConstraints() { ->exampleConstraints : () => void +function inconsistentParameters() { +>inconsistentParameters : () => void - class Parent { ->Parent : Parent + class Parent { +>Parent : Parent a: A; >a : A - } - class Child extends Parent { ->Child : Child ->Parent : Parent b: B; >b : B } + class Child extends Parent { +>Child : Child +>Parent : Parent - const objPass: Parent<1 | 2 | 3> = undefined as any; ->objPass : Parent<1 | 2 | 3> ->undefined as any : any ->undefined : undefined - - if (objPass instanceof Child) { ->objPass instanceof Child : boolean ->objPass : Parent<1 | 2 | 3> ->Child : typeof Child - - objPass; // expect: Child<1 | 2 | 3> ->objPass : Child<1 | 2 | 3> - } - - const obj12: Parent<1 | 2> = undefined as any; ->obj12 : Parent<1 | 2> ->undefined as any : any ->undefined : undefined - - if (obj12 instanceof Child) { ->obj12 instanceof Child : boolean ->obj12 : Parent<1 | 2> ->Child : typeof Child - - obj12; // expect: Child<1 | 2> ->obj12 : Child<1 | 2> + c: C; +>c : C } + function possible(p: Parent) { +>possible : (p: Parent) => void +>p : Parent - const objFail: Parent = undefined as any; ->objFail : Parent ->undefined as any : any ->undefined : undefined - - if (objFail instanceof Child) { ->objFail instanceof Child : boolean ->objFail : Parent + if (p instanceof Child) { +>p instanceof Child : boolean +>p : Parent >Child : typeof Child - objFail; // Child, since string and 1|2|3 have no overlap. ->objFail : Child - } - - const objRefine: Parent = undefined as any; ->objRefine : Parent ->undefined as any : any ->undefined : undefined - - if (objRefine instanceof Child) { ->objRefine instanceof Child : boolean ->objRefine : Parent ->Child : typeof Child + p; +>p : Child - objRefine; // expect: Child<1 | 2 | 3> ->objRefine : Child<1 | 2 | 3> + } else { + p; +>p : Parent + } } + function impossible(p: Parent) { +>impossible : (p: Parent) => void +>p : Parent - const objRefine1234: Parent<1 | 2 | 3 | 4> = undefined as any; ->objRefine1234 : Parent<1 | 2 | 3 | 4> ->undefined as any : any ->undefined : undefined - - if (objRefine1234 instanceof Child) { ->objRefine1234 instanceof Child : boolean ->objRefine1234 : Parent<1 | 2 | 3 | 4> + if (p instanceof Child) { +>p instanceof Child : boolean +>p : Parent >Child : typeof Child - objRefine1234; // expect: Child<1 | 2 | 3> ->objRefine1234 : Child<1 | 2 | 3> - } + p; +>p : Child - const objOverlap: Parent<2 | 3 | 4 | 5> = undefined as any; ->objOverlap : Parent<2 | 3 | 4 | 5> ->undefined as any : any ->undefined : undefined - - if (objOverlap instanceof Child) { ->objOverlap instanceof Child : boolean ->objOverlap : Parent<2 | 3 | 4 | 5> ->Child : typeof Child - - objOverlap; // ideally, Child<2 | 3>, but actually Child since 2|3|4|5 is not a supertype of 1|2|3. ->objOverlap : Child + } else { + p; +>p : Parent + } } } -function exampleUnrelated() { ->exampleUnrelated : () => void +function union() { +>union : () => void - class Child { ->Child : Child + class Parent { +>Parent : Parent a: A; >a : A + } + class Child extends Parent { +>Child : Child +>Parent : Parent b: B; >b : B - - foo: number; ->foo : number } + function multipleParents( +>multipleParents : (p: Parent | Parent | Parent) => void - const objA = { a: 5 }; ->objA : { a: number; } ->{ a: 5 } : { a: number; } ->a : number ->5 : 5 + p: Parent | Parent | Parent +>p : Parent | Parent | Parent - if (objA instanceof Child) { ->objA instanceof Child : boolean ->objA : { a: number; } + ) { + if (p instanceof Child) { +>p instanceof Child : boolean +>p : Parent | Parent | Parent >Child : typeof Child - objA; // Child ->objA : Child - } - - const objB = { b: "hello" }; ->objB : { b: string; } ->{ b: "hello" } : { b: string; } ->b : string ->"hello" : "hello" - - if (objB instanceof Child) { ->objB instanceof Child : boolean ->objB : { b: string; } ->Child : typeof Child + p; +>p : Child | Child | Child - objB; // Child ->objB : Child + } else { + p; +>p : Parent | Parent | Parent + } } + function mixedChildren(p: Parent | Child) { +>mixedChildren : (p: Parent | Child) => void +>p : Parent | Child - const objAB = { a: 5, b: "hello" }; ->objAB : { a: number; b: string; } ->{ a: 5, b: "hello" } : { a: number; b: string; } ->a : number ->5 : 5 ->b : string ->"hello" : "hello" - - if (objAB instanceof Child) { ->objAB instanceof Child : boolean ->objAB : { a: number; b: string; } + if (p instanceof Child) { +>p instanceof Child : boolean +>p : Parent | Child >Child : typeof Child - objAB; // Child ->objAB : Child - } - - const objAX = { a: 5, x: 7 }; ->objAX : { a: number; x: number; } ->{ a: 5, x: 7 } : { a: number; x: number; } ->a : number ->5 : 5 ->x : number ->7 : 7 - - if (objAX instanceof Child) { ->objAX instanceof Child : boolean ->objAX : { a: number; x: number; } ->Child : typeof Child + p; +>p : Child - objAX; // Child ->objAX : { a: number; x: number; } & Child + } else { + p; +>p : Parent + } } + function imcompatibleOptions( +>imcompatibleOptions : (p: Parent | Parent | { foo: boolean; }) => void - const objBX = { b: "hello", x: 7 }; ->objBX : { b: string; x: number; } ->{ b: "hello", x: 7 } : { b: string; x: number; } ->b : string ->"hello" : "hello" ->x : number ->7 : 7 + p: Parent | Parent | { foo: boolean } +>p : Parent | Parent | { foo: boolean; } +>foo : boolean - if (objBX instanceof Child) { ->objBX instanceof Child : boolean ->objBX : { b: string; x: number; } + ) { + if (p instanceof Child) { +>p instanceof Child : boolean +>p : Parent | Parent | { foo: boolean; } >Child : typeof Child - objBX; // Child ->objBX : { b: string; x: number; } & Child - } - - const objABX = { a: 5, b: "hello", x: 7 }; ->objABX : { a: number; b: string; x: number; } ->{ a: 5, b: "hello", x: 7 } : { a: number; b: string; x: number; } ->a : number ->5 : 5 ->b : string ->"hello" : "hello" ->x : number ->7 : 7 - - if (objABX instanceof Child) { ->objABX instanceof Child : boolean ->objABX : { a: number; b: string; x: number; } ->Child : typeof Child + p; +>p : Child - objABX; // Child ->objABX : { a: number; b: string; x: number; } & Child + } else { + p; +>p : Parent | Parent | { foo: boolean; } + } } } diff --git a/tests/cases/compiler/narrowGenericTypeByInstanceOf.ts b/tests/cases/compiler/narrowGenericTypeByInstanceOf.ts index 1cc65e29a78a0..0425a146f8b9b 100644 --- a/tests/cases/compiler/narrowGenericTypeByInstanceOf.ts +++ b/tests/cases/compiler/narrowGenericTypeByInstanceOf.ts @@ -1,226 +1,200 @@ -function exampleSingleArgument() { +// From #28560 + +function preserveParentParameters() { class Parent { value: T; } - - class Child extends Parent { - other: T; + class Child extends Parent { + other: S; } - const obj: Parent = undefined as any; - - if (obj instanceof Child) { - obj; + function withNumber(p: Parent) { + if (p instanceof Child) { + p; + } else { + p; + } } -} -function exampleSingleExtendsMultiple() { - class Parent { - value1: A; - value2: B; - } - - class Child extends Parent { - other: T; + function withString(p: Parent) { + if (p instanceof Child) { + p; + } else { + p; + } } - - const obj: Parent = undefined as any; - - if (obj instanceof Child) { - obj; + function withGeneric(p: Parent) { + if (p instanceof Child) { + p; + } else { + p; + } } } -function exampleSwapParameterOrder() { - class Parent { - value1: A; - value2: B; +function copyParameterStructurally() { + class Parent { + value: T; } - - class Child extends Parent { - value3: C; - value4: D; + class Child { + value: S; + other: S; } - const obj: Parent = undefined as any; - - if (obj instanceof Child) { - obj; + function withNumber(p: Parent) { + if (p instanceof Child) { + p; + } else { + p; + } } -} - -function exampleSingleExtendsMultipleReject() { - class Parent { - value1: A; - value2: B; + function withString(p: Parent) { + if (p instanceof Child) { + p; + } else { + p; + } } - - class Child extends Parent { - value3: C; - } - - const obj: Parent = undefined as any; - - if (obj instanceof Child) { - obj; + function withGeneric(p: Parent) { + if (p instanceof Child) { + p; + } else { + p; + } } } -function exampleUnion() { - class Parent { - value1: A; - value2: B; +function useConstraint() { + // #17473 + interface Foo { + foo: string; } - class Child extends Parent { - value3: C; + class Bar { + constructor(readonly bar: T) {} } - const obj0: - | Parent<{ foo: string }, { foo: string }> - | Parent - | Parent = undefined as any; - if (obj0 instanceof Child) { - obj0; + let a: any; + if (a instanceof Bar) { + a.bar; // <-- a.bar should be 'Foo' instead of 'any' } +} - const obj1 = undefined as Parent<{ foo: string }, { foo: string }>; - if (obj1 instanceof Child) { - obj1; +function enhanceConstraint() { + class Parent { + value: T; } - - const obj2 = undefined as Parent; - if (obj2 instanceof Child) { - obj2; + class Child extends Parent { + other: T; } - const obj3 = undefined as Parent; - if (obj3 instanceof Child) { - obj3; + function simpleExtends(p: Parent<1 | 2 | 3 | 4>) { + if (p instanceof Child) { + p; + } else { + p; + } } - - const obj4 = undefined as string | { foo: string }; - if (obj4 instanceof Child) { - obj4; + function complexExtends(p: Parent<2 | 3>) { + if (p instanceof Child) { + p; + } else { + p; + } } - const obj5 = undefined as { foo: string }; - if (obj5 instanceof Child) { - obj5; + function impossibleExtends(p: Parent<3 | 4>) { + if (p instanceof Child) { + p; + } else { + p; + } } } -function exampleNegative() { - class Parent { - value1: A; - value2: B; - } - - class Child extends Parent { - value3: C; +function dontWidenPointlessly() { + class Query { + uses: T; } - - const obj: - | Parent - | Parent - | Child = undefined as any; - - if (obj instanceof Child) { - // Here we filter out matching ones, instead of just narrowing to them. - obj; - return; + function f(p: T[] | Query) { + if (Array.isArray(p)) { + p; // T[], so far so good + } else if (p instanceof Query) { + p; // should be Query, not Query + } } - - console.log(obj); } -function exampleIgnoreDefaults() { - // default parameters shouldn't have any impact on this narrowing. - class Parent { +function multipleParameters() { + class Parent { a: A; + b: B; } - class Child extends Parent { - a2: A2; - c: C; + class Swapped extends Parent { + x: X; + y: Y; } - - const obj: Parent = undefined as any; - if (obj instanceof Child) { - obj; + function checkSwapped(p: Parent) { + if (p instanceof Swapped) { + p; + } else { + p; + } } } -function exampleConstraints() { - class Parent { +function inconsistentParameters() { + class Parent { a: A; - } - class Child extends Parent { b: B; } - - const objPass: Parent<1 | 2 | 3> = undefined as any; - if (objPass instanceof Child) { - objPass; // expect: Child<1 | 2 | 3> - } - - const obj12: Parent<1 | 2> = undefined as any; - if (obj12 instanceof Child) { - obj12; // expect: Child<1 | 2> - } - - const objFail: Parent = undefined as any; - if (objFail instanceof Child) { - objFail; // Child, since string and 1|2|3 have no overlap. - } - - const objRefine: Parent = undefined as any; - if (objRefine instanceof Child) { - objRefine; // expect: Child<1 | 2 | 3> + class Child extends Parent { + c: C; } - - const objRefine1234: Parent<1 | 2 | 3 | 4> = undefined as any; - if (objRefine1234 instanceof Child) { - objRefine1234; // expect: Child<1 | 2 | 3> + function possible(p: Parent) { + if (p instanceof Child) { + p; + } else { + p; + } } - - const objOverlap: Parent<2 | 3 | 4 | 5> = undefined as any; - if (objOverlap instanceof Child) { - objOverlap; // ideally, Child<2 | 3>, but actually Child since 2|3|4|5 is not a supertype of 1|2|3. + function impossible(p: Parent) { + if (p instanceof Child) { + p; + } else { + p; + } } } -function exampleUnrelated() { - class Child { +function union() { + class Parent { a: A; - b: B; - foo: number; - } - - const objA = { a: 5 }; - if (objA instanceof Child) { - objA; // Child } - - const objB = { b: "hello" }; - if (objB instanceof Child) { - objB; // Child - } - - const objAB = { a: 5, b: "hello" }; - if (objAB instanceof Child) { - objAB; // Child - } - - const objAX = { a: 5, x: 7 }; - if (objAX instanceof Child) { - objAX; // Child - } - - const objBX = { b: "hello", x: 7 }; - if (objBX instanceof Child) { - objBX; // Child + class Child extends Parent { + b: B; } - - const objABX = { a: 5, b: "hello", x: 7 }; - if (objABX instanceof Child) { - objABX; // Child + function multipleParents( + p: Parent | Parent | Parent + ) { + if (p instanceof Child) { + p; + } else { + p; + } + } + function mixedChildren(p: Parent | Child) { + if (p instanceof Child) { + p; + } else { + p; + } + } + function imcompatibleOptions( + p: Parent | Parent | { foo: boolean } + ) { + if (p instanceof Child) { + p; + } else { + p; + } } }