Merge pull request #4165 from RyanCavanaugh/useAssignabilityForInstanceofTypeguard
Use different relation for `instanceof` type guards
This commit is contained in:
commit
8a6426272e
|
@ -6219,14 +6219,20 @@ namespace ts {
|
|||
}
|
||||
|
||||
function getNarrowedType(originalType: Type, narrowedTypeCandidate: Type) {
|
||||
// Narrow to the target type if it's a subtype of the current type
|
||||
if (isTypeSubtypeOf(narrowedTypeCandidate, originalType)) {
|
||||
// If the current type is a union type, remove all constituents that aren't assignable to target. If that produces
|
||||
// 0 candidates, fall back to the assignability check
|
||||
if (originalType.flags & TypeFlags.Union) {
|
||||
let assignableConstituents = filter((<UnionType>originalType).types, t => isTypeAssignableTo(t, narrowedTypeCandidate));
|
||||
if (assignableConstituents.length) {
|
||||
return getUnionType(assignableConstituents);
|
||||
}
|
||||
}
|
||||
|
||||
if (isTypeAssignableTo(narrowedTypeCandidate, originalType)) {
|
||||
// Narrow to the target type if it's assignable to the current type
|
||||
return narrowedTypeCandidate;
|
||||
}
|
||||
// If the current type is a union type, remove all constituents that aren't subtypes of the target.
|
||||
if (originalType.flags & TypeFlags.Union) {
|
||||
return getUnionType(filter((<UnionType>originalType).types, t => isTypeSubtypeOf(t, narrowedTypeCandidate)));
|
||||
}
|
||||
|
||||
return originalType;
|
||||
}
|
||||
|
||||
|
|
187
tests/baselines/reference/instanceOfAssignability.js
Normal file
187
tests/baselines/reference/instanceOfAssignability.js
Normal file
|
@ -0,0 +1,187 @@
|
|||
//// [instanceOfAssignability.ts]
|
||||
interface Base {
|
||||
foo: string|number;
|
||||
optional?: number;
|
||||
}
|
||||
|
||||
// Derived1 is assignable to, but not a subtype of, Base
|
||||
class Derived1 implements Base {
|
||||
foo: string;
|
||||
}
|
||||
// Derived2 is a subtype of Base that is not assignable to Derived1
|
||||
class Derived2 implements Base {
|
||||
foo: number;
|
||||
optional: number;
|
||||
}
|
||||
|
||||
class Animal {
|
||||
move;
|
||||
}
|
||||
class Mammal extends Animal { milk; }
|
||||
class Giraffe extends Mammal { neck; }
|
||||
|
||||
function fn1(x: Array<number>|Array<string>|boolean) {
|
||||
if(x instanceof Array) {
|
||||
// 1.5: y: Array<number>|Array<string>
|
||||
// Want: y: Array<number>|Array<string>
|
||||
let y = x;
|
||||
}
|
||||
}
|
||||
|
||||
function fn2(x: Base) {
|
||||
if(x instanceof Derived1) {
|
||||
// 1.5: y: Base
|
||||
// Want: y: Derived1
|
||||
let y = x;
|
||||
}
|
||||
}
|
||||
|
||||
function fn3(x: Base|Derived1) {
|
||||
if(x instanceof Derived2) {
|
||||
// 1.5: y: Derived2
|
||||
// Want: Derived2
|
||||
let y = x;
|
||||
}
|
||||
}
|
||||
|
||||
function fn4(x: Base|Derived2) {
|
||||
if(x instanceof Derived1) {
|
||||
// 1.5: y: {}
|
||||
// Want: Derived1
|
||||
let y = x;
|
||||
}
|
||||
}
|
||||
|
||||
function fn5(x: Derived1) {
|
||||
if(x instanceof Derived2) {
|
||||
// 1.5: y: Derived1
|
||||
// Want: ???
|
||||
let y = x;
|
||||
}
|
||||
}
|
||||
|
||||
function fn6(x: Animal|Mammal) {
|
||||
if(x instanceof Giraffe) {
|
||||
// 1.5: y: Derived1
|
||||
// Want: ???
|
||||
let y = x;
|
||||
}
|
||||
}
|
||||
|
||||
function fn7(x: Array<number>|Array<string>) {
|
||||
if(x instanceof Array) {
|
||||
// 1.5: y: Array<number>|Array<string>
|
||||
// Want: y: Array<number>|Array<string>
|
||||
let y = x;
|
||||
}
|
||||
}
|
||||
|
||||
interface Alpha { a }
|
||||
interface Beta { b }
|
||||
interface Gamma { c }
|
||||
class ABC { a; b; c; }
|
||||
function fn8(x: Alpha|Beta|Gamma) {
|
||||
if(x instanceof ABC) {
|
||||
let y = x;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//// [instanceOfAssignability.js]
|
||||
var __extends = (this && this.__extends) || function (d, b) {
|
||||
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
|
||||
function __() { this.constructor = d; }
|
||||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||
};
|
||||
// Derived1 is assignable to, but not a subtype of, Base
|
||||
var Derived1 = (function () {
|
||||
function Derived1() {
|
||||
}
|
||||
return Derived1;
|
||||
})();
|
||||
// Derived2 is a subtype of Base that is not assignable to Derived1
|
||||
var Derived2 = (function () {
|
||||
function Derived2() {
|
||||
}
|
||||
return Derived2;
|
||||
})();
|
||||
var Animal = (function () {
|
||||
function Animal() {
|
||||
}
|
||||
return Animal;
|
||||
})();
|
||||
var Mammal = (function (_super) {
|
||||
__extends(Mammal, _super);
|
||||
function Mammal() {
|
||||
_super.apply(this, arguments);
|
||||
}
|
||||
return Mammal;
|
||||
})(Animal);
|
||||
var Giraffe = (function (_super) {
|
||||
__extends(Giraffe, _super);
|
||||
function Giraffe() {
|
||||
_super.apply(this, arguments);
|
||||
}
|
||||
return Giraffe;
|
||||
})(Mammal);
|
||||
function fn1(x) {
|
||||
if (x instanceof Array) {
|
||||
// 1.5: y: Array<number>|Array<string>
|
||||
// Want: y: Array<number>|Array<string>
|
||||
var y = x;
|
||||
}
|
||||
}
|
||||
function fn2(x) {
|
||||
if (x instanceof Derived1) {
|
||||
// 1.5: y: Base
|
||||
// Want: y: Derived1
|
||||
var y = x;
|
||||
}
|
||||
}
|
||||
function fn3(x) {
|
||||
if (x instanceof Derived2) {
|
||||
// 1.5: y: Derived2
|
||||
// Want: Derived2
|
||||
var y = x;
|
||||
}
|
||||
}
|
||||
function fn4(x) {
|
||||
if (x instanceof Derived1) {
|
||||
// 1.5: y: {}
|
||||
// Want: Derived1
|
||||
var y = x;
|
||||
}
|
||||
}
|
||||
function fn5(x) {
|
||||
if (x instanceof Derived2) {
|
||||
// 1.5: y: Derived1
|
||||
// Want: ???
|
||||
var y = x;
|
||||
}
|
||||
}
|
||||
function fn6(x) {
|
||||
if (x instanceof Giraffe) {
|
||||
// 1.5: y: Derived1
|
||||
// Want: ???
|
||||
var y = x;
|
||||
}
|
||||
}
|
||||
function fn7(x) {
|
||||
if (x instanceof Array) {
|
||||
// 1.5: y: Array<number>|Array<string>
|
||||
// Want: y: Array<number>|Array<string>
|
||||
var y = x;
|
||||
}
|
||||
}
|
||||
var ABC = (function () {
|
||||
function ABC() {
|
||||
}
|
||||
return ABC;
|
||||
})();
|
||||
function fn8(x) {
|
||||
if (x instanceof ABC) {
|
||||
var y = x;
|
||||
}
|
||||
}
|
208
tests/baselines/reference/instanceOfAssignability.symbols
Normal file
208
tests/baselines/reference/instanceOfAssignability.symbols
Normal file
|
@ -0,0 +1,208 @@
|
|||
=== tests/cases/compiler/instanceOfAssignability.ts ===
|
||||
interface Base {
|
||||
>Base : Symbol(Base, Decl(instanceOfAssignability.ts, 0, 0))
|
||||
|
||||
foo: string|number;
|
||||
>foo : Symbol(foo, Decl(instanceOfAssignability.ts, 0, 16))
|
||||
|
||||
optional?: number;
|
||||
>optional : Symbol(optional, Decl(instanceOfAssignability.ts, 1, 20))
|
||||
}
|
||||
|
||||
// Derived1 is assignable to, but not a subtype of, Base
|
||||
class Derived1 implements Base {
|
||||
>Derived1 : Symbol(Derived1, Decl(instanceOfAssignability.ts, 3, 1))
|
||||
>Base : Symbol(Base, Decl(instanceOfAssignability.ts, 0, 0))
|
||||
|
||||
foo: string;
|
||||
>foo : Symbol(foo, Decl(instanceOfAssignability.ts, 6, 32))
|
||||
}
|
||||
// Derived2 is a subtype of Base that is not assignable to Derived1
|
||||
class Derived2 implements Base {
|
||||
>Derived2 : Symbol(Derived2, Decl(instanceOfAssignability.ts, 8, 1))
|
||||
>Base : Symbol(Base, Decl(instanceOfAssignability.ts, 0, 0))
|
||||
|
||||
foo: number;
|
||||
>foo : Symbol(foo, Decl(instanceOfAssignability.ts, 10, 32))
|
||||
|
||||
optional: number;
|
||||
>optional : Symbol(optional, Decl(instanceOfAssignability.ts, 11, 13))
|
||||
}
|
||||
|
||||
class Animal {
|
||||
>Animal : Symbol(Animal, Decl(instanceOfAssignability.ts, 13, 1))
|
||||
|
||||
move;
|
||||
>move : Symbol(move, Decl(instanceOfAssignability.ts, 15, 14))
|
||||
}
|
||||
class Mammal extends Animal { milk; }
|
||||
>Mammal : Symbol(Mammal, Decl(instanceOfAssignability.ts, 17, 1))
|
||||
>Animal : Symbol(Animal, Decl(instanceOfAssignability.ts, 13, 1))
|
||||
>milk : Symbol(milk, Decl(instanceOfAssignability.ts, 18, 29))
|
||||
|
||||
class Giraffe extends Mammal { neck; }
|
||||
>Giraffe : Symbol(Giraffe, Decl(instanceOfAssignability.ts, 18, 37))
|
||||
>Mammal : Symbol(Mammal, Decl(instanceOfAssignability.ts, 17, 1))
|
||||
>neck : Symbol(neck, Decl(instanceOfAssignability.ts, 19, 30))
|
||||
|
||||
function fn1(x: Array<number>|Array<string>|boolean) {
|
||||
>fn1 : Symbol(fn1, Decl(instanceOfAssignability.ts, 19, 38))
|
||||
>x : Symbol(x, Decl(instanceOfAssignability.ts, 21, 13))
|
||||
>Array : Symbol(Array, Decl(lib.d.ts, 1000, 23), Decl(lib.d.ts, 1171, 11))
|
||||
>Array : Symbol(Array, Decl(lib.d.ts, 1000, 23), Decl(lib.d.ts, 1171, 11))
|
||||
|
||||
if(x instanceof Array) {
|
||||
>x : Symbol(x, Decl(instanceOfAssignability.ts, 21, 13))
|
||||
>Array : Symbol(Array, Decl(lib.d.ts, 1000, 23), Decl(lib.d.ts, 1171, 11))
|
||||
|
||||
// 1.5: y: Array<number>|Array<string>
|
||||
// Want: y: Array<number>|Array<string>
|
||||
let y = x;
|
||||
>y : Symbol(y, Decl(instanceOfAssignability.ts, 25, 5))
|
||||
>x : Symbol(x, Decl(instanceOfAssignability.ts, 21, 13))
|
||||
}
|
||||
}
|
||||
|
||||
function fn2(x: Base) {
|
||||
>fn2 : Symbol(fn2, Decl(instanceOfAssignability.ts, 27, 1))
|
||||
>x : Symbol(x, Decl(instanceOfAssignability.ts, 29, 13))
|
||||
>Base : Symbol(Base, Decl(instanceOfAssignability.ts, 0, 0))
|
||||
|
||||
if(x instanceof Derived1) {
|
||||
>x : Symbol(x, Decl(instanceOfAssignability.ts, 29, 13))
|
||||
>Derived1 : Symbol(Derived1, Decl(instanceOfAssignability.ts, 3, 1))
|
||||
|
||||
// 1.5: y: Base
|
||||
// Want: y: Derived1
|
||||
let y = x;
|
||||
>y : Symbol(y, Decl(instanceOfAssignability.ts, 33, 5))
|
||||
>x : Symbol(x, Decl(instanceOfAssignability.ts, 29, 13))
|
||||
}
|
||||
}
|
||||
|
||||
function fn3(x: Base|Derived1) {
|
||||
>fn3 : Symbol(fn3, Decl(instanceOfAssignability.ts, 35, 1))
|
||||
>x : Symbol(x, Decl(instanceOfAssignability.ts, 37, 13))
|
||||
>Base : Symbol(Base, Decl(instanceOfAssignability.ts, 0, 0))
|
||||
>Derived1 : Symbol(Derived1, Decl(instanceOfAssignability.ts, 3, 1))
|
||||
|
||||
if(x instanceof Derived2) {
|
||||
>x : Symbol(x, Decl(instanceOfAssignability.ts, 37, 13))
|
||||
>Derived2 : Symbol(Derived2, Decl(instanceOfAssignability.ts, 8, 1))
|
||||
|
||||
// 1.5: y: Derived2
|
||||
// Want: Derived2
|
||||
let y = x;
|
||||
>y : Symbol(y, Decl(instanceOfAssignability.ts, 41, 5))
|
||||
>x : Symbol(x, Decl(instanceOfAssignability.ts, 37, 13))
|
||||
}
|
||||
}
|
||||
|
||||
function fn4(x: Base|Derived2) {
|
||||
>fn4 : Symbol(fn4, Decl(instanceOfAssignability.ts, 43, 1))
|
||||
>x : Symbol(x, Decl(instanceOfAssignability.ts, 45, 13))
|
||||
>Base : Symbol(Base, Decl(instanceOfAssignability.ts, 0, 0))
|
||||
>Derived2 : Symbol(Derived2, Decl(instanceOfAssignability.ts, 8, 1))
|
||||
|
||||
if(x instanceof Derived1) {
|
||||
>x : Symbol(x, Decl(instanceOfAssignability.ts, 45, 13))
|
||||
>Derived1 : Symbol(Derived1, Decl(instanceOfAssignability.ts, 3, 1))
|
||||
|
||||
// 1.5: y: {}
|
||||
// Want: Derived1
|
||||
let y = x;
|
||||
>y : Symbol(y, Decl(instanceOfAssignability.ts, 49, 5))
|
||||
>x : Symbol(x, Decl(instanceOfAssignability.ts, 45, 13))
|
||||
}
|
||||
}
|
||||
|
||||
function fn5(x: Derived1) {
|
||||
>fn5 : Symbol(fn5, Decl(instanceOfAssignability.ts, 51, 1))
|
||||
>x : Symbol(x, Decl(instanceOfAssignability.ts, 53, 13))
|
||||
>Derived1 : Symbol(Derived1, Decl(instanceOfAssignability.ts, 3, 1))
|
||||
|
||||
if(x instanceof Derived2) {
|
||||
>x : Symbol(x, Decl(instanceOfAssignability.ts, 53, 13))
|
||||
>Derived2 : Symbol(Derived2, Decl(instanceOfAssignability.ts, 8, 1))
|
||||
|
||||
// 1.5: y: Derived1
|
||||
// Want: ???
|
||||
let y = x;
|
||||
>y : Symbol(y, Decl(instanceOfAssignability.ts, 57, 5))
|
||||
>x : Symbol(x, Decl(instanceOfAssignability.ts, 53, 13))
|
||||
}
|
||||
}
|
||||
|
||||
function fn6(x: Animal|Mammal) {
|
||||
>fn6 : Symbol(fn6, Decl(instanceOfAssignability.ts, 59, 1))
|
||||
>x : Symbol(x, Decl(instanceOfAssignability.ts, 61, 13))
|
||||
>Animal : Symbol(Animal, Decl(instanceOfAssignability.ts, 13, 1))
|
||||
>Mammal : Symbol(Mammal, Decl(instanceOfAssignability.ts, 17, 1))
|
||||
|
||||
if(x instanceof Giraffe) {
|
||||
>x : Symbol(x, Decl(instanceOfAssignability.ts, 61, 13))
|
||||
>Giraffe : Symbol(Giraffe, Decl(instanceOfAssignability.ts, 18, 37))
|
||||
|
||||
// 1.5: y: Derived1
|
||||
// Want: ???
|
||||
let y = x;
|
||||
>y : Symbol(y, Decl(instanceOfAssignability.ts, 65, 5))
|
||||
>x : Symbol(x, Decl(instanceOfAssignability.ts, 61, 13))
|
||||
}
|
||||
}
|
||||
|
||||
function fn7(x: Array<number>|Array<string>) {
|
||||
>fn7 : Symbol(fn7, Decl(instanceOfAssignability.ts, 67, 1))
|
||||
>x : Symbol(x, Decl(instanceOfAssignability.ts, 69, 13))
|
||||
>Array : Symbol(Array, Decl(lib.d.ts, 1000, 23), Decl(lib.d.ts, 1171, 11))
|
||||
>Array : Symbol(Array, Decl(lib.d.ts, 1000, 23), Decl(lib.d.ts, 1171, 11))
|
||||
|
||||
if(x instanceof Array) {
|
||||
>x : Symbol(x, Decl(instanceOfAssignability.ts, 69, 13))
|
||||
>Array : Symbol(Array, Decl(lib.d.ts, 1000, 23), Decl(lib.d.ts, 1171, 11))
|
||||
|
||||
// 1.5: y: Array<number>|Array<string>
|
||||
// Want: y: Array<number>|Array<string>
|
||||
let y = x;
|
||||
>y : Symbol(y, Decl(instanceOfAssignability.ts, 73, 5))
|
||||
>x : Symbol(x, Decl(instanceOfAssignability.ts, 69, 13))
|
||||
}
|
||||
}
|
||||
|
||||
interface Alpha { a }
|
||||
>Alpha : Symbol(Alpha, Decl(instanceOfAssignability.ts, 75, 1))
|
||||
>a : Symbol(a, Decl(instanceOfAssignability.ts, 77, 17))
|
||||
|
||||
interface Beta { b }
|
||||
>Beta : Symbol(Beta, Decl(instanceOfAssignability.ts, 77, 21))
|
||||
>b : Symbol(b, Decl(instanceOfAssignability.ts, 78, 16))
|
||||
|
||||
interface Gamma { c }
|
||||
>Gamma : Symbol(Gamma, Decl(instanceOfAssignability.ts, 78, 20))
|
||||
>c : Symbol(c, Decl(instanceOfAssignability.ts, 79, 17))
|
||||
|
||||
class ABC { a; b; c; }
|
||||
>ABC : Symbol(ABC, Decl(instanceOfAssignability.ts, 79, 21))
|
||||
>a : Symbol(a, Decl(instanceOfAssignability.ts, 80, 11))
|
||||
>b : Symbol(b, Decl(instanceOfAssignability.ts, 80, 14))
|
||||
>c : Symbol(c, Decl(instanceOfAssignability.ts, 80, 17))
|
||||
|
||||
function fn8(x: Alpha|Beta|Gamma) {
|
||||
>fn8 : Symbol(fn8, Decl(instanceOfAssignability.ts, 80, 22))
|
||||
>x : Symbol(x, Decl(instanceOfAssignability.ts, 81, 13))
|
||||
>Alpha : Symbol(Alpha, Decl(instanceOfAssignability.ts, 75, 1))
|
||||
>Beta : Symbol(Beta, Decl(instanceOfAssignability.ts, 77, 21))
|
||||
>Gamma : Symbol(Gamma, Decl(instanceOfAssignability.ts, 78, 20))
|
||||
|
||||
if(x instanceof ABC) {
|
||||
>x : Symbol(x, Decl(instanceOfAssignability.ts, 81, 13))
|
||||
>ABC : Symbol(ABC, Decl(instanceOfAssignability.ts, 79, 21))
|
||||
|
||||
let y = x;
|
||||
>y : Symbol(y, Decl(instanceOfAssignability.ts, 83, 5))
|
||||
>x : Symbol(x, Decl(instanceOfAssignability.ts, 81, 13))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
216
tests/baselines/reference/instanceOfAssignability.types
Normal file
216
tests/baselines/reference/instanceOfAssignability.types
Normal file
|
@ -0,0 +1,216 @@
|
|||
=== tests/cases/compiler/instanceOfAssignability.ts ===
|
||||
interface Base {
|
||||
>Base : Base
|
||||
|
||||
foo: string|number;
|
||||
>foo : string | number
|
||||
|
||||
optional?: number;
|
||||
>optional : number
|
||||
}
|
||||
|
||||
// Derived1 is assignable to, but not a subtype of, Base
|
||||
class Derived1 implements Base {
|
||||
>Derived1 : Derived1
|
||||
>Base : Base
|
||||
|
||||
foo: string;
|
||||
>foo : string
|
||||
}
|
||||
// Derived2 is a subtype of Base that is not assignable to Derived1
|
||||
class Derived2 implements Base {
|
||||
>Derived2 : Derived2
|
||||
>Base : Base
|
||||
|
||||
foo: number;
|
||||
>foo : number
|
||||
|
||||
optional: number;
|
||||
>optional : number
|
||||
}
|
||||
|
||||
class Animal {
|
||||
>Animal : Animal
|
||||
|
||||
move;
|
||||
>move : any
|
||||
}
|
||||
class Mammal extends Animal { milk; }
|
||||
>Mammal : Mammal
|
||||
>Animal : Animal
|
||||
>milk : any
|
||||
|
||||
class Giraffe extends Mammal { neck; }
|
||||
>Giraffe : Giraffe
|
||||
>Mammal : Mammal
|
||||
>neck : any
|
||||
|
||||
function fn1(x: Array<number>|Array<string>|boolean) {
|
||||
>fn1 : (x: number[] | string[] | boolean) => void
|
||||
>x : number[] | string[] | boolean
|
||||
>Array : T[]
|
||||
>Array : T[]
|
||||
|
||||
if(x instanceof Array) {
|
||||
>x instanceof Array : boolean
|
||||
>x : number[] | string[] | boolean
|
||||
>Array : ArrayConstructor
|
||||
|
||||
// 1.5: y: Array<number>|Array<string>
|
||||
// Want: y: Array<number>|Array<string>
|
||||
let y = x;
|
||||
>y : number[] | string[]
|
||||
>x : number[] | string[]
|
||||
}
|
||||
}
|
||||
|
||||
function fn2(x: Base) {
|
||||
>fn2 : (x: Base) => void
|
||||
>x : Base
|
||||
>Base : Base
|
||||
|
||||
if(x instanceof Derived1) {
|
||||
>x instanceof Derived1 : boolean
|
||||
>x : Base
|
||||
>Derived1 : typeof Derived1
|
||||
|
||||
// 1.5: y: Base
|
||||
// Want: y: Derived1
|
||||
let y = x;
|
||||
>y : Derived1
|
||||
>x : Derived1
|
||||
}
|
||||
}
|
||||
|
||||
function fn3(x: Base|Derived1) {
|
||||
>fn3 : (x: Base | Derived1) => void
|
||||
>x : Base | Derived1
|
||||
>Base : Base
|
||||
>Derived1 : Derived1
|
||||
|
||||
if(x instanceof Derived2) {
|
||||
>x instanceof Derived2 : boolean
|
||||
>x : Base | Derived1
|
||||
>Derived2 : typeof Derived2
|
||||
|
||||
// 1.5: y: Derived2
|
||||
// Want: Derived2
|
||||
let y = x;
|
||||
>y : Derived2
|
||||
>x : Derived2
|
||||
}
|
||||
}
|
||||
|
||||
function fn4(x: Base|Derived2) {
|
||||
>fn4 : (x: Base | Derived2) => void
|
||||
>x : Base | Derived2
|
||||
>Base : Base
|
||||
>Derived2 : Derived2
|
||||
|
||||
if(x instanceof Derived1) {
|
||||
>x instanceof Derived1 : boolean
|
||||
>x : Base | Derived2
|
||||
>Derived1 : typeof Derived1
|
||||
|
||||
// 1.5: y: {}
|
||||
// Want: Derived1
|
||||
let y = x;
|
||||
>y : Derived1
|
||||
>x : Derived1
|
||||
}
|
||||
}
|
||||
|
||||
function fn5(x: Derived1) {
|
||||
>fn5 : (x: Derived1) => void
|
||||
>x : Derived1
|
||||
>Derived1 : Derived1
|
||||
|
||||
if(x instanceof Derived2) {
|
||||
>x instanceof Derived2 : boolean
|
||||
>x : Derived1
|
||||
>Derived2 : typeof Derived2
|
||||
|
||||
// 1.5: y: Derived1
|
||||
// Want: ???
|
||||
let y = x;
|
||||
>y : Derived1
|
||||
>x : Derived1
|
||||
}
|
||||
}
|
||||
|
||||
function fn6(x: Animal|Mammal) {
|
||||
>fn6 : (x: Animal | Mammal) => void
|
||||
>x : Animal | Mammal
|
||||
>Animal : Animal
|
||||
>Mammal : Mammal
|
||||
|
||||
if(x instanceof Giraffe) {
|
||||
>x instanceof Giraffe : boolean
|
||||
>x : Animal | Mammal
|
||||
>Giraffe : typeof Giraffe
|
||||
|
||||
// 1.5: y: Derived1
|
||||
// Want: ???
|
||||
let y = x;
|
||||
>y : Giraffe
|
||||
>x : Giraffe
|
||||
}
|
||||
}
|
||||
|
||||
function fn7(x: Array<number>|Array<string>) {
|
||||
>fn7 : (x: number[] | string[]) => void
|
||||
>x : number[] | string[]
|
||||
>Array : T[]
|
||||
>Array : T[]
|
||||
|
||||
if(x instanceof Array) {
|
||||
>x instanceof Array : boolean
|
||||
>x : number[] | string[]
|
||||
>Array : ArrayConstructor
|
||||
|
||||
// 1.5: y: Array<number>|Array<string>
|
||||
// Want: y: Array<number>|Array<string>
|
||||
let y = x;
|
||||
>y : number[] | string[]
|
||||
>x : number[] | string[]
|
||||
}
|
||||
}
|
||||
|
||||
interface Alpha { a }
|
||||
>Alpha : Alpha
|
||||
>a : any
|
||||
|
||||
interface Beta { b }
|
||||
>Beta : Beta
|
||||
>b : any
|
||||
|
||||
interface Gamma { c }
|
||||
>Gamma : Gamma
|
||||
>c : any
|
||||
|
||||
class ABC { a; b; c; }
|
||||
>ABC : ABC
|
||||
>a : any
|
||||
>b : any
|
||||
>c : any
|
||||
|
||||
function fn8(x: Alpha|Beta|Gamma) {
|
||||
>fn8 : (x: Alpha | Beta | Gamma) => void
|
||||
>x : Alpha | Beta | Gamma
|
||||
>Alpha : Alpha
|
||||
>Beta : Beta
|
||||
>Gamma : Gamma
|
||||
|
||||
if(x instanceof ABC) {
|
||||
>x instanceof ABC : boolean
|
||||
>x : Alpha | Beta | Gamma
|
||||
>ABC : typeof ABC
|
||||
|
||||
let y = x;
|
||||
>y : ABC
|
||||
>x : ABC
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1,18 +1,16 @@
|
|||
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(12,10): error TS2339: Property 'bar' does not exist on type 'A'.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(33,5): error TS2322: Type 'string' is not assignable to type 'number'.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(34,10): error TS2339: Property 'bar' does not exist on type 'B<number>'.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(65,10): error TS2339: Property 'bar1' does not exist on type 'C1 | C2'.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(66,10): error TS2339: Property 'bar2' does not exist on type 'C1 | C2'.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(66,10): error TS2339: Property 'bar2' does not exist on type 'C1'.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(85,10): error TS2339: Property 'bar' does not exist on type 'D'.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(111,10): error TS2339: Property 'bar1' does not exist on type 'E1 | E2'.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(112,10): error TS2339: Property 'bar2' does not exist on type 'E1 | E2'.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(112,10): error TS2339: Property 'bar2' does not exist on type 'E1'.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(134,11): error TS2339: Property 'foo' does not exist on type 'F | string'.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(135,11): error TS2339: Property 'bar' does not exist on type 'F | string'.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(160,11): error TS2339: Property 'foo2' does not exist on type 'G1'.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(182,11): error TS2339: Property 'bar' does not exist on type 'H'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts (12 errors) ====
|
||||
==== tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts (10 errors) ====
|
||||
interface AConstructor {
|
||||
new (): A;
|
||||
}
|
||||
|
@ -84,11 +82,9 @@ tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstru
|
|||
obj5.foo;
|
||||
obj5.c;
|
||||
obj5.bar1;
|
||||
~~~~
|
||||
!!! error TS2339: Property 'bar1' does not exist on type 'C1 | C2'.
|
||||
obj5.bar2;
|
||||
~~~~
|
||||
!!! error TS2339: Property 'bar2' does not exist on type 'C1 | C2'.
|
||||
!!! error TS2339: Property 'bar2' does not exist on type 'C1'.
|
||||
}
|
||||
|
||||
var obj6: any;
|
||||
|
@ -136,11 +132,9 @@ tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstru
|
|||
if (obj9 instanceof E) { // narrowed to E1 | E2
|
||||
obj9.foo;
|
||||
obj9.bar1;
|
||||
~~~~
|
||||
!!! error TS2339: Property 'bar1' does not exist on type 'E1 | E2'.
|
||||
obj9.bar2;
|
||||
~~~~
|
||||
!!! error TS2339: Property 'bar2' does not exist on type 'E1 | E2'.
|
||||
!!! error TS2339: Property 'bar2' does not exist on type 'E1'.
|
||||
}
|
||||
|
||||
var obj10: any;
|
||||
|
|
88
tests/cases/compiler/instanceOfAssignability.ts
Normal file
88
tests/cases/compiler/instanceOfAssignability.ts
Normal file
|
@ -0,0 +1,88 @@
|
|||
interface Base {
|
||||
foo: string|number;
|
||||
optional?: number;
|
||||
}
|
||||
|
||||
// Derived1 is assignable to, but not a subtype of, Base
|
||||
class Derived1 implements Base {
|
||||
foo: string;
|
||||
}
|
||||
// Derived2 is a subtype of Base that is not assignable to Derived1
|
||||
class Derived2 implements Base {
|
||||
foo: number;
|
||||
optional: number;
|
||||
}
|
||||
|
||||
class Animal {
|
||||
move;
|
||||
}
|
||||
class Mammal extends Animal { milk; }
|
||||
class Giraffe extends Mammal { neck; }
|
||||
|
||||
function fn1(x: Array<number>|Array<string>|boolean) {
|
||||
if(x instanceof Array) {
|
||||
// 1.5: y: Array<number>|Array<string>
|
||||
// Want: y: Array<number>|Array<string>
|
||||
let y = x;
|
||||
}
|
||||
}
|
||||
|
||||
function fn2(x: Base) {
|
||||
if(x instanceof Derived1) {
|
||||
// 1.5: y: Base
|
||||
// Want: y: Derived1
|
||||
let y = x;
|
||||
}
|
||||
}
|
||||
|
||||
function fn3(x: Base|Derived1) {
|
||||
if(x instanceof Derived2) {
|
||||
// 1.5: y: Derived2
|
||||
// Want: Derived2
|
||||
let y = x;
|
||||
}
|
||||
}
|
||||
|
||||
function fn4(x: Base|Derived2) {
|
||||
if(x instanceof Derived1) {
|
||||
// 1.5: y: {}
|
||||
// Want: Derived1
|
||||
let y = x;
|
||||
}
|
||||
}
|
||||
|
||||
function fn5(x: Derived1) {
|
||||
if(x instanceof Derived2) {
|
||||
// 1.5: y: Derived1
|
||||
// Want: ???
|
||||
let y = x;
|
||||
}
|
||||
}
|
||||
|
||||
function fn6(x: Animal|Mammal) {
|
||||
if(x instanceof Giraffe) {
|
||||
// 1.5: y: Derived1
|
||||
// Want: ???
|
||||
let y = x;
|
||||
}
|
||||
}
|
||||
|
||||
function fn7(x: Array<number>|Array<string>) {
|
||||
if(x instanceof Array) {
|
||||
// 1.5: y: Array<number>|Array<string>
|
||||
// Want: y: Array<number>|Array<string>
|
||||
let y = x;
|
||||
}
|
||||
}
|
||||
|
||||
interface Alpha { a }
|
||||
interface Beta { b }
|
||||
interface Gamma { c }
|
||||
class ABC { a; b; c; }
|
||||
function fn8(x: Alpha|Beta|Gamma) {
|
||||
if(x instanceof ABC) {
|
||||
let y = x;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in a new issue