Merge pull request #5906 from weswigham/this-type-guards

This type predicates for type guards
This commit is contained in:
Wesley Wigham
2015-12-09 17:22:39 -08:00
30 changed files with 2943 additions and 178 deletions

View File

@@ -4,7 +4,7 @@ var obj: Object;
>Object : Object
if (ArrayBuffer.isView(obj)) {
>ArrayBuffer.isView(obj) : boolean
>ArrayBuffer.isView(obj) : arg is ArrayBufferView
>ArrayBuffer.isView : (arg: any) => arg is ArrayBufferView
>ArrayBuffer : ArrayBufferConstructor
>isView : (arg: any) => arg is ArrayBufferView

View File

@@ -4,7 +4,7 @@ var maybeArray: number | number[];
if (Array.isArray(maybeArray)) {
>Array.isArray(maybeArray) : boolean
>Array.isArray(maybeArray) : arg is any[]
>Array.isArray : (arg: any) => arg is any[]
>Array : ArrayConstructor
>isArray : (arg: any) => arg is any[]

View File

@@ -31,7 +31,7 @@ function f(foo: T) {
>T : ("a" | "b")[] | "a" | "b"
if (isS(foo)) {
>isS(foo) : boolean
>isS(foo) : t is "a" | "b"
>isS : (t: ("a" | "b")[] | "a" | "b") => t is "a" | "b"
>foo : ("a" | "b")[] | "a" | "b"

View File

@@ -1,10 +1,8 @@
tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTags01.ts(18,10): error TS2382: Specialized overload signature is not assignable to any non-specialized signature.
tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTags01.ts(19,10): error TS2382: Specialized overload signature is not assignable to any non-specialized signature.
tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTags01.ts(20,10): error TS2394: Overload signature is not compatible with function implementation.
tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTags01.ts(22,21): error TS2304: Cannot find name 'is'.
==== tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTags01.ts (4 errors) ====
==== tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTags01.ts (2 errors) ====
type Kind = "A" | "B"
@@ -23,11 +21,7 @@ tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTags01.ts(22,21)
}
function hasKind(entity: Entity, kind: "A"): entity is A;
~~~~~~~
!!! error TS2382: Specialized overload signature is not assignable to any non-specialized signature.
function hasKind(entity: Entity, kind: "B"): entity is B;
~~~~~~~
!!! error TS2382: Specialized overload signature is not assignable to any non-specialized signature.
function hasKind(entity: Entity, kind: Kind): entity is Entity;
~~~~~~~
!!! error TS2394: Overload signature is not compatible with function implementation.

View File

@@ -54,7 +54,7 @@ var b: B;
// Basic
if (isC(a)) {
>isC(a) : boolean
>isC(a) : p1 is C
>isC : (p1: any) => p1 is C
>a : A
@@ -70,7 +70,7 @@ var subType: C;
>C : C
if(isA(subType)) {
>isA(subType) : boolean
>isA(subType) : p1 is A
>isA : (p1: any) => p1 is A
>subType : C
@@ -87,7 +87,7 @@ var union: A | B;
>B : B
if(isA(union)) {
>isA(union) : boolean
>isA(union) : p1 is A
>isA : (p1: any) => p1 is A
>union : A | B
@@ -118,7 +118,7 @@ declare function isC_multipleParams(p1, p2): p1 is C;
>C : C
if (isC_multipleParams(a, 0)) {
>isC_multipleParams(a, 0) : boolean
>isC_multipleParams(a, 0) : p1 is C
>isC_multipleParams : (p1: any, p2: any) => p1 is C
>a : A
>0 : number
@@ -197,7 +197,7 @@ declare function acceptingBoolean(a: boolean);
acceptingBoolean(isA(a));
>acceptingBoolean(isA(a)) : any
>acceptingBoolean : (a: boolean) => any
>isA(a) : boolean
>isA(a) : p1 is A
>isA : (p1: any) => p1 is A
>a : A
@@ -223,8 +223,8 @@ let union2: C | B;
let union3: boolean | B = isA(union2) || union2;
>union3 : boolean | B
>B : B
>isA(union2) || union2 : boolean | B
>isA(union2) : boolean
>isA(union2) || union2 : p1 is A | B
>isA(union2) : p1 is A
>isA : (p1: any) => p1 is A
>union2 : C | B
>union2 : B

View File

@@ -1,4 +1,4 @@
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(15,12): error TS2322: Type 'string' is not assignable to type 'boolean'.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(15,12): error TS2322: Type 'string' is not assignable to type 'x is A'.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(22,33): error TS2304: Cannot find name 'x'.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(26,33): error TS1225: Cannot find parameter 'x'.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(30,10): error TS2391: Function implementation is missing or not immediately following the declaration.
@@ -16,6 +16,7 @@ tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(70,7):
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(75,46): error TS2345: Argument of type '(p1: any) => p1 is C' is not assignable to parameter of type '(p1: any) => p1 is B'.
Type predicate 'p1 is C' is not assignable to 'p1 is B'.
Type 'C' is not assignable to type 'B'.
Property 'propB' is missing in type 'C'.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(79,1): error TS2322: Type '(p1: any, p2: any) => boolean' is not assignable to type '(p1: any, p2: any) => p1 is A'.
Signature '(p1: any, p2: any): boolean' must have a type predicate.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(85,1): error TS2322: Type '(p1: any, p2: any) => p2 is A' is not assignable to type '(p1: any, p2: any) => p1 is A'.
@@ -25,7 +26,6 @@ tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(91,1):
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(96,9): error TS1228: A type predicate is only allowed in return type position for functions and methods.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(97,16): error TS1228: A type predicate is only allowed in return type position for functions and methods.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(98,20): error TS1228: A type predicate is only allowed in return type position for functions and methods.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(104,25): error TS1228: A type predicate is only allowed in return type position for functions and methods.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(105,16): error TS2322: Type 'boolean' is not assignable to type 'D'.
Property 'm1' is missing in type 'Boolean'.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(105,16): error TS2409: Return type of constructor signature must be assignable to the instance type of the class
@@ -33,6 +33,7 @@ tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(107,20
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(110,20): error TS1228: A type predicate is only allowed in return type position for functions and methods.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(111,16): error TS2408: Setters cannot return a value.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(116,18): error TS1228: A type predicate is only allowed in return type position for functions and methods.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(120,22): error TS1225: Cannot find parameter 'p1'.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(120,22): error TS1228: A type predicate is only allowed in return type position for functions and methods.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(124,20): error TS1229: A type predicate cannot reference a rest parameter.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(129,34): error TS1230: A type predicate cannot reference element 'p1' in a binding pattern.
@@ -57,7 +58,7 @@ tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(137,39
function hasANonBooleanReturnStatement(x): x is A {
return '';
~~
!!! error TS2322: Type 'string' is not assignable to type 'boolean'.
!!! error TS2322: Type 'string' is not assignable to type 'x is A'.
}
function hasTypeGuardTypeInsideTypeGuardType(x): x is x is A {
@@ -149,6 +150,7 @@ tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(137,39
!!! error TS2345: Argument of type '(p1: any) => p1 is C' is not assignable to parameter of type '(p1: any) => p1 is B'.
!!! error TS2345: Type predicate 'p1 is C' is not assignable to 'p1 is B'.
!!! error TS2345: Type 'C' is not assignable to type 'B'.
!!! error TS2345: Property 'propB' is missing in type 'C'.
// Boolean not assignable to type guard
var assign1: (p1, p2) => p1 is A;
@@ -193,8 +195,6 @@ tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(137,39
// Non-compatiable type predicate positions for signature declarations
class D {
constructor(p1: A): p1 is C {
~~~~~~~
!!! error TS1228: A type predicate is only allowed in return type position for functions and methods.
return true;
~~~~
!!! error TS2322: Type 'boolean' is not assignable to type 'D'.
@@ -224,6 +224,8 @@ tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(137,39
interface I2 {
[index: number]: p1 is C;
~~
!!! error TS1225: Cannot find parameter 'p1'.
~~~~~~~
!!! error TS1228: A type predicate is only allowed in return type position for functions and methods.
}

View File

@@ -100,7 +100,7 @@ let test1: boolean = funA(isB);
>isB : (p1: any) => p1 is B
if (funB(retC, a)) {
>funB(retC, a) : boolean
>funB(retC, a) : p2 is C
>funB : <T>(p1: (p1: any) => T, p2: any) => p2 is T
>retC : (x: any) => C
>a : A
@@ -118,7 +118,7 @@ let test2: B = funC(isB);
>isB : (p1: any) => p1 is B
if (funD(isC, a)) {
>funD(isC, a) : boolean
>funD(isC, a) : p2 is C
>funD : <T>(p1: (p1: any) => p1 is T, p2: any) => p2 is T
>isC : (p1: any) => p1 is C
>a : A

View File

@@ -0,0 +1,347 @@
//// [typeGuardFunctionOfFormThis.ts]
class RoyalGuard {
isLeader(): this is LeadGuard {
return this instanceof LeadGuard;
}
isFollower(): this is FollowerGuard {
return this instanceof FollowerGuard;
}
}
class LeadGuard extends RoyalGuard {
lead(): void {};
}
class FollowerGuard extends RoyalGuard {
follow(): void {};
}
let a: RoyalGuard = new FollowerGuard();
if (a.isLeader()) {
a.lead();
}
else if (a.isFollower()) {
a.follow();
}
interface GuardInterface extends RoyalGuard {}
let b: GuardInterface;
if (b.isLeader()) {
b.lead();
}
else if (b.isFollower()) {
b.follow();
}
if (((a.isLeader)())) {
a.lead();
}
else if (((a).isFollower())) {
a.follow();
}
if (((a["isLeader"])())) {
a.lead();
}
else if (((a)["isFollower"]())) {
a.follow();
}
var holder2 = {a};
if (holder2.a.isLeader()) {
holder2.a;
}
else {
holder2.a;
}
class ArrowGuard {
isElite = (): this is ArrowElite => {
return this instanceof ArrowElite;
}
isMedic = (): this is ArrowMedic => {
return this instanceof ArrowMedic;
}
}
class ArrowElite extends ArrowGuard {
defend(): void {}
}
class ArrowMedic extends ArrowGuard {
heal(): void {}
}
let guard = new ArrowGuard();
if (guard.isElite()) {
guard.defend();
}
else if (guard.isMedic()) {
guard.heal();
}
interface Supplies {
spoiled: boolean;
}
interface Sundries {
broken: boolean;
}
interface Crate<T> {
contents: T;
volume: number;
isSupplies(): this is Crate<Supplies>;
isSundries(): this is Crate<Sundries>;
}
let crate: Crate<{}>;
if (crate.isSundries()) {
crate.contents.broken = true;
}
else if (crate.isSupplies()) {
crate.contents.spoiled = true;
}
// Matching guards should be assignable
a.isFollower = b.isFollower;
a.isLeader = b.isLeader;
class MimicGuard {
isLeader(): this is MimicLeader { return this instanceof MimicLeader; };
isFollower(): this is MimicFollower { return this instanceof MimicFollower; };
}
class MimicLeader extends MimicGuard {
lead(): void {}
}
class MimicFollower extends MimicGuard {
follow(): void {}
}
let mimic = new MimicGuard();
a.isLeader = mimic.isLeader;
a.isFollower = mimic.isFollower;
if (mimic.isFollower()) {
mimic.follow();
mimic.isFollower = a.isFollower;
}
interface MimicGuardInterface {
isLeader(): this is LeadGuard;
isFollower(): this is FollowerGuard;
}
//// [typeGuardFunctionOfFormThis.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 __());
};
var RoyalGuard = (function () {
function RoyalGuard() {
}
RoyalGuard.prototype.isLeader = function () {
return this instanceof LeadGuard;
};
RoyalGuard.prototype.isFollower = function () {
return this instanceof FollowerGuard;
};
return RoyalGuard;
}());
var LeadGuard = (function (_super) {
__extends(LeadGuard, _super);
function LeadGuard() {
_super.apply(this, arguments);
}
LeadGuard.prototype.lead = function () { };
;
return LeadGuard;
}(RoyalGuard));
var FollowerGuard = (function (_super) {
__extends(FollowerGuard, _super);
function FollowerGuard() {
_super.apply(this, arguments);
}
FollowerGuard.prototype.follow = function () { };
;
return FollowerGuard;
}(RoyalGuard));
var a = new FollowerGuard();
if (a.isLeader()) {
a.lead();
}
else if (a.isFollower()) {
a.follow();
}
var b;
if (b.isLeader()) {
b.lead();
}
else if (b.isFollower()) {
b.follow();
}
if (((a.isLeader)())) {
a.lead();
}
else if (((a).isFollower())) {
a.follow();
}
if (((a["isLeader"])())) {
a.lead();
}
else if (((a)["isFollower"]())) {
a.follow();
}
var holder2 = { a: a };
if (holder2.a.isLeader()) {
holder2.a;
}
else {
holder2.a;
}
var ArrowGuard = (function () {
function ArrowGuard() {
var _this = this;
this.isElite = function () {
return _this instanceof ArrowElite;
};
this.isMedic = function () {
return _this instanceof ArrowMedic;
};
}
return ArrowGuard;
}());
var ArrowElite = (function (_super) {
__extends(ArrowElite, _super);
function ArrowElite() {
_super.apply(this, arguments);
}
ArrowElite.prototype.defend = function () { };
return ArrowElite;
}(ArrowGuard));
var ArrowMedic = (function (_super) {
__extends(ArrowMedic, _super);
function ArrowMedic() {
_super.apply(this, arguments);
}
ArrowMedic.prototype.heal = function () { };
return ArrowMedic;
}(ArrowGuard));
var guard = new ArrowGuard();
if (guard.isElite()) {
guard.defend();
}
else if (guard.isMedic()) {
guard.heal();
}
var crate;
if (crate.isSundries()) {
crate.contents.broken = true;
}
else if (crate.isSupplies()) {
crate.contents.spoiled = true;
}
// Matching guards should be assignable
a.isFollower = b.isFollower;
a.isLeader = b.isLeader;
var MimicGuard = (function () {
function MimicGuard() {
}
MimicGuard.prototype.isLeader = function () { return this instanceof MimicLeader; };
;
MimicGuard.prototype.isFollower = function () { return this instanceof MimicFollower; };
;
return MimicGuard;
}());
var MimicLeader = (function (_super) {
__extends(MimicLeader, _super);
function MimicLeader() {
_super.apply(this, arguments);
}
MimicLeader.prototype.lead = function () { };
return MimicLeader;
}(MimicGuard));
var MimicFollower = (function (_super) {
__extends(MimicFollower, _super);
function MimicFollower() {
_super.apply(this, arguments);
}
MimicFollower.prototype.follow = function () { };
return MimicFollower;
}(MimicGuard));
var mimic = new MimicGuard();
a.isLeader = mimic.isLeader;
a.isFollower = mimic.isFollower;
if (mimic.isFollower()) {
mimic.follow();
mimic.isFollower = a.isFollower;
}
//// [typeGuardFunctionOfFormThis.d.ts]
declare class RoyalGuard {
isLeader(): this is LeadGuard;
isFollower(): this is FollowerGuard;
}
declare class LeadGuard extends RoyalGuard {
lead(): void;
}
declare class FollowerGuard extends RoyalGuard {
follow(): void;
}
declare let a: RoyalGuard;
interface GuardInterface extends RoyalGuard {
}
declare let b: GuardInterface;
declare var holder2: {
a: RoyalGuard;
};
declare class ArrowGuard {
isElite: () => this is ArrowElite;
isMedic: () => this is ArrowMedic;
}
declare class ArrowElite extends ArrowGuard {
defend(): void;
}
declare class ArrowMedic extends ArrowGuard {
heal(): void;
}
declare let guard: ArrowGuard;
interface Supplies {
spoiled: boolean;
}
interface Sundries {
broken: boolean;
}
interface Crate<T> {
contents: T;
volume: number;
isSupplies(): this is Crate<Supplies>;
isSundries(): this is Crate<Sundries>;
}
declare let crate: Crate<{}>;
declare class MimicGuard {
isLeader(): this is MimicLeader;
isFollower(): this is MimicFollower;
}
declare class MimicLeader extends MimicGuard {
lead(): void;
}
declare class MimicFollower extends MimicGuard {
follow(): void;
}
declare let mimic: MimicGuard;
interface MimicGuardInterface {
isLeader(): this is LeadGuard;
isFollower(): this is FollowerGuard;
}

View File

@@ -0,0 +1,385 @@
=== tests/cases/conformance/expressions/typeGuards/typeGuardFunctionOfFormThis.ts ===
class RoyalGuard {
>RoyalGuard : Symbol(RoyalGuard, Decl(typeGuardFunctionOfFormThis.ts, 0, 0))
isLeader(): this is LeadGuard {
>isLeader : Symbol(isLeader, Decl(typeGuardFunctionOfFormThis.ts, 0, 18))
>LeadGuard : Symbol(LeadGuard, Decl(typeGuardFunctionOfFormThis.ts, 7, 1))
return this instanceof LeadGuard;
>this : Symbol(RoyalGuard, Decl(typeGuardFunctionOfFormThis.ts, 0, 0))
>LeadGuard : Symbol(LeadGuard, Decl(typeGuardFunctionOfFormThis.ts, 7, 1))
}
isFollower(): this is FollowerGuard {
>isFollower : Symbol(isFollower, Decl(typeGuardFunctionOfFormThis.ts, 3, 5))
>FollowerGuard : Symbol(FollowerGuard, Decl(typeGuardFunctionOfFormThis.ts, 11, 1))
return this instanceof FollowerGuard;
>this : Symbol(RoyalGuard, Decl(typeGuardFunctionOfFormThis.ts, 0, 0))
>FollowerGuard : Symbol(FollowerGuard, Decl(typeGuardFunctionOfFormThis.ts, 11, 1))
}
}
class LeadGuard extends RoyalGuard {
>LeadGuard : Symbol(LeadGuard, Decl(typeGuardFunctionOfFormThis.ts, 7, 1))
>RoyalGuard : Symbol(RoyalGuard, Decl(typeGuardFunctionOfFormThis.ts, 0, 0))
lead(): void {};
>lead : Symbol(lead, Decl(typeGuardFunctionOfFormThis.ts, 9, 36))
}
class FollowerGuard extends RoyalGuard {
>FollowerGuard : Symbol(FollowerGuard, Decl(typeGuardFunctionOfFormThis.ts, 11, 1))
>RoyalGuard : Symbol(RoyalGuard, Decl(typeGuardFunctionOfFormThis.ts, 0, 0))
follow(): void {};
>follow : Symbol(follow, Decl(typeGuardFunctionOfFormThis.ts, 13, 40))
}
let a: RoyalGuard = new FollowerGuard();
>a : Symbol(a, Decl(typeGuardFunctionOfFormThis.ts, 17, 3))
>RoyalGuard : Symbol(RoyalGuard, Decl(typeGuardFunctionOfFormThis.ts, 0, 0))
>FollowerGuard : Symbol(FollowerGuard, Decl(typeGuardFunctionOfFormThis.ts, 11, 1))
if (a.isLeader()) {
>a.isLeader : Symbol(RoyalGuard.isLeader, Decl(typeGuardFunctionOfFormThis.ts, 0, 18))
>a : Symbol(a, Decl(typeGuardFunctionOfFormThis.ts, 17, 3))
>isLeader : Symbol(RoyalGuard.isLeader, Decl(typeGuardFunctionOfFormThis.ts, 0, 18))
a.lead();
>a.lead : Symbol(LeadGuard.lead, Decl(typeGuardFunctionOfFormThis.ts, 9, 36))
>a : Symbol(a, Decl(typeGuardFunctionOfFormThis.ts, 17, 3))
>lead : Symbol(LeadGuard.lead, Decl(typeGuardFunctionOfFormThis.ts, 9, 36))
}
else if (a.isFollower()) {
>a.isFollower : Symbol(RoyalGuard.isFollower, Decl(typeGuardFunctionOfFormThis.ts, 3, 5))
>a : Symbol(a, Decl(typeGuardFunctionOfFormThis.ts, 17, 3))
>isFollower : Symbol(RoyalGuard.isFollower, Decl(typeGuardFunctionOfFormThis.ts, 3, 5))
a.follow();
>a.follow : Symbol(FollowerGuard.follow, Decl(typeGuardFunctionOfFormThis.ts, 13, 40))
>a : Symbol(a, Decl(typeGuardFunctionOfFormThis.ts, 17, 3))
>follow : Symbol(FollowerGuard.follow, Decl(typeGuardFunctionOfFormThis.ts, 13, 40))
}
interface GuardInterface extends RoyalGuard {}
>GuardInterface : Symbol(GuardInterface, Decl(typeGuardFunctionOfFormThis.ts, 23, 1))
>RoyalGuard : Symbol(RoyalGuard, Decl(typeGuardFunctionOfFormThis.ts, 0, 0))
let b: GuardInterface;
>b : Symbol(b, Decl(typeGuardFunctionOfFormThis.ts, 27, 3))
>GuardInterface : Symbol(GuardInterface, Decl(typeGuardFunctionOfFormThis.ts, 23, 1))
if (b.isLeader()) {
>b.isLeader : Symbol(RoyalGuard.isLeader, Decl(typeGuardFunctionOfFormThis.ts, 0, 18))
>b : Symbol(b, Decl(typeGuardFunctionOfFormThis.ts, 27, 3))
>isLeader : Symbol(RoyalGuard.isLeader, Decl(typeGuardFunctionOfFormThis.ts, 0, 18))
b.lead();
>b.lead : Symbol(LeadGuard.lead, Decl(typeGuardFunctionOfFormThis.ts, 9, 36))
>b : Symbol(b, Decl(typeGuardFunctionOfFormThis.ts, 27, 3))
>lead : Symbol(LeadGuard.lead, Decl(typeGuardFunctionOfFormThis.ts, 9, 36))
}
else if (b.isFollower()) {
>b.isFollower : Symbol(RoyalGuard.isFollower, Decl(typeGuardFunctionOfFormThis.ts, 3, 5))
>b : Symbol(b, Decl(typeGuardFunctionOfFormThis.ts, 27, 3))
>isFollower : Symbol(RoyalGuard.isFollower, Decl(typeGuardFunctionOfFormThis.ts, 3, 5))
b.follow();
>b.follow : Symbol(FollowerGuard.follow, Decl(typeGuardFunctionOfFormThis.ts, 13, 40))
>b : Symbol(b, Decl(typeGuardFunctionOfFormThis.ts, 27, 3))
>follow : Symbol(FollowerGuard.follow, Decl(typeGuardFunctionOfFormThis.ts, 13, 40))
}
if (((a.isLeader)())) {
>a.isLeader : Symbol(RoyalGuard.isLeader, Decl(typeGuardFunctionOfFormThis.ts, 0, 18))
>a : Symbol(a, Decl(typeGuardFunctionOfFormThis.ts, 17, 3))
>isLeader : Symbol(RoyalGuard.isLeader, Decl(typeGuardFunctionOfFormThis.ts, 0, 18))
a.lead();
>a.lead : Symbol(LeadGuard.lead, Decl(typeGuardFunctionOfFormThis.ts, 9, 36))
>a : Symbol(a, Decl(typeGuardFunctionOfFormThis.ts, 17, 3))
>lead : Symbol(LeadGuard.lead, Decl(typeGuardFunctionOfFormThis.ts, 9, 36))
}
else if (((a).isFollower())) {
>(a).isFollower : Symbol(RoyalGuard.isFollower, Decl(typeGuardFunctionOfFormThis.ts, 3, 5))
>a : Symbol(a, Decl(typeGuardFunctionOfFormThis.ts, 17, 3))
>isFollower : Symbol(RoyalGuard.isFollower, Decl(typeGuardFunctionOfFormThis.ts, 3, 5))
a.follow();
>a.follow : Symbol(FollowerGuard.follow, Decl(typeGuardFunctionOfFormThis.ts, 13, 40))
>a : Symbol(a, Decl(typeGuardFunctionOfFormThis.ts, 17, 3))
>follow : Symbol(FollowerGuard.follow, Decl(typeGuardFunctionOfFormThis.ts, 13, 40))
}
if (((a["isLeader"])())) {
>a : Symbol(a, Decl(typeGuardFunctionOfFormThis.ts, 17, 3))
>"isLeader" : Symbol(RoyalGuard.isLeader, Decl(typeGuardFunctionOfFormThis.ts, 0, 18))
a.lead();
>a.lead : Symbol(LeadGuard.lead, Decl(typeGuardFunctionOfFormThis.ts, 9, 36))
>a : Symbol(a, Decl(typeGuardFunctionOfFormThis.ts, 17, 3))
>lead : Symbol(LeadGuard.lead, Decl(typeGuardFunctionOfFormThis.ts, 9, 36))
}
else if (((a)["isFollower"]())) {
>a : Symbol(a, Decl(typeGuardFunctionOfFormThis.ts, 17, 3))
>"isFollower" : Symbol(RoyalGuard.isFollower, Decl(typeGuardFunctionOfFormThis.ts, 3, 5))
a.follow();
>a.follow : Symbol(FollowerGuard.follow, Decl(typeGuardFunctionOfFormThis.ts, 13, 40))
>a : Symbol(a, Decl(typeGuardFunctionOfFormThis.ts, 17, 3))
>follow : Symbol(FollowerGuard.follow, Decl(typeGuardFunctionOfFormThis.ts, 13, 40))
}
var holder2 = {a};
>holder2 : Symbol(holder2, Decl(typeGuardFunctionOfFormThis.ts, 49, 3))
>a : Symbol(a, Decl(typeGuardFunctionOfFormThis.ts, 49, 15))
if (holder2.a.isLeader()) {
>holder2.a.isLeader : Symbol(RoyalGuard.isLeader, Decl(typeGuardFunctionOfFormThis.ts, 0, 18))
>holder2.a : Symbol(a, Decl(typeGuardFunctionOfFormThis.ts, 49, 15))
>holder2 : Symbol(holder2, Decl(typeGuardFunctionOfFormThis.ts, 49, 3))
>a : Symbol(a, Decl(typeGuardFunctionOfFormThis.ts, 49, 15))
>isLeader : Symbol(RoyalGuard.isLeader, Decl(typeGuardFunctionOfFormThis.ts, 0, 18))
holder2.a;
>holder2.a : Symbol(a, Decl(typeGuardFunctionOfFormThis.ts, 49, 15))
>holder2 : Symbol(holder2, Decl(typeGuardFunctionOfFormThis.ts, 49, 3))
>a : Symbol(a, Decl(typeGuardFunctionOfFormThis.ts, 49, 15))
}
else {
holder2.a;
>holder2.a : Symbol(a, Decl(typeGuardFunctionOfFormThis.ts, 49, 15))
>holder2 : Symbol(holder2, Decl(typeGuardFunctionOfFormThis.ts, 49, 3))
>a : Symbol(a, Decl(typeGuardFunctionOfFormThis.ts, 49, 15))
}
class ArrowGuard {
>ArrowGuard : Symbol(ArrowGuard, Decl(typeGuardFunctionOfFormThis.ts, 56, 1))
isElite = (): this is ArrowElite => {
>isElite : Symbol(isElite, Decl(typeGuardFunctionOfFormThis.ts, 58, 18))
>ArrowElite : Symbol(ArrowElite, Decl(typeGuardFunctionOfFormThis.ts, 65, 1))
return this instanceof ArrowElite;
>this : Symbol(ArrowGuard, Decl(typeGuardFunctionOfFormThis.ts, 56, 1))
>ArrowElite : Symbol(ArrowElite, Decl(typeGuardFunctionOfFormThis.ts, 65, 1))
}
isMedic = (): this is ArrowMedic => {
>isMedic : Symbol(isMedic, Decl(typeGuardFunctionOfFormThis.ts, 61, 5))
>ArrowMedic : Symbol(ArrowMedic, Decl(typeGuardFunctionOfFormThis.ts, 69, 1))
return this instanceof ArrowMedic;
>this : Symbol(ArrowGuard, Decl(typeGuardFunctionOfFormThis.ts, 56, 1))
>ArrowMedic : Symbol(ArrowMedic, Decl(typeGuardFunctionOfFormThis.ts, 69, 1))
}
}
class ArrowElite extends ArrowGuard {
>ArrowElite : Symbol(ArrowElite, Decl(typeGuardFunctionOfFormThis.ts, 65, 1))
>ArrowGuard : Symbol(ArrowGuard, Decl(typeGuardFunctionOfFormThis.ts, 56, 1))
defend(): void {}
>defend : Symbol(defend, Decl(typeGuardFunctionOfFormThis.ts, 67, 37))
}
class ArrowMedic extends ArrowGuard {
>ArrowMedic : Symbol(ArrowMedic, Decl(typeGuardFunctionOfFormThis.ts, 69, 1))
>ArrowGuard : Symbol(ArrowGuard, Decl(typeGuardFunctionOfFormThis.ts, 56, 1))
heal(): void {}
>heal : Symbol(heal, Decl(typeGuardFunctionOfFormThis.ts, 71, 37))
}
let guard = new ArrowGuard();
>guard : Symbol(guard, Decl(typeGuardFunctionOfFormThis.ts, 75, 3))
>ArrowGuard : Symbol(ArrowGuard, Decl(typeGuardFunctionOfFormThis.ts, 56, 1))
if (guard.isElite()) {
>guard.isElite : Symbol(ArrowGuard.isElite, Decl(typeGuardFunctionOfFormThis.ts, 58, 18))
>guard : Symbol(guard, Decl(typeGuardFunctionOfFormThis.ts, 75, 3))
>isElite : Symbol(ArrowGuard.isElite, Decl(typeGuardFunctionOfFormThis.ts, 58, 18))
guard.defend();
>guard.defend : Symbol(ArrowElite.defend, Decl(typeGuardFunctionOfFormThis.ts, 67, 37))
>guard : Symbol(guard, Decl(typeGuardFunctionOfFormThis.ts, 75, 3))
>defend : Symbol(ArrowElite.defend, Decl(typeGuardFunctionOfFormThis.ts, 67, 37))
}
else if (guard.isMedic()) {
>guard.isMedic : Symbol(ArrowGuard.isMedic, Decl(typeGuardFunctionOfFormThis.ts, 61, 5))
>guard : Symbol(guard, Decl(typeGuardFunctionOfFormThis.ts, 75, 3))
>isMedic : Symbol(ArrowGuard.isMedic, Decl(typeGuardFunctionOfFormThis.ts, 61, 5))
guard.heal();
>guard.heal : Symbol(ArrowMedic.heal, Decl(typeGuardFunctionOfFormThis.ts, 71, 37))
>guard : Symbol(guard, Decl(typeGuardFunctionOfFormThis.ts, 75, 3))
>heal : Symbol(ArrowMedic.heal, Decl(typeGuardFunctionOfFormThis.ts, 71, 37))
}
interface Supplies {
>Supplies : Symbol(Supplies, Decl(typeGuardFunctionOfFormThis.ts, 81, 1))
spoiled: boolean;
>spoiled : Symbol(spoiled, Decl(typeGuardFunctionOfFormThis.ts, 83, 20))
}
interface Sundries {
>Sundries : Symbol(Sundries, Decl(typeGuardFunctionOfFormThis.ts, 85, 1))
broken: boolean;
>broken : Symbol(broken, Decl(typeGuardFunctionOfFormThis.ts, 87, 20))
}
interface Crate<T> {
>Crate : Symbol(Crate, Decl(typeGuardFunctionOfFormThis.ts, 89, 1))
>T : Symbol(T, Decl(typeGuardFunctionOfFormThis.ts, 91, 16))
contents: T;
>contents : Symbol(contents, Decl(typeGuardFunctionOfFormThis.ts, 91, 20))
>T : Symbol(T, Decl(typeGuardFunctionOfFormThis.ts, 91, 16))
volume: number;
>volume : Symbol(volume, Decl(typeGuardFunctionOfFormThis.ts, 92, 16))
isSupplies(): this is Crate<Supplies>;
>isSupplies : Symbol(isSupplies, Decl(typeGuardFunctionOfFormThis.ts, 93, 19))
>Crate : Symbol(Crate, Decl(typeGuardFunctionOfFormThis.ts, 89, 1))
>Supplies : Symbol(Supplies, Decl(typeGuardFunctionOfFormThis.ts, 81, 1))
isSundries(): this is Crate<Sundries>;
>isSundries : Symbol(isSundries, Decl(typeGuardFunctionOfFormThis.ts, 94, 42))
>Crate : Symbol(Crate, Decl(typeGuardFunctionOfFormThis.ts, 89, 1))
>Sundries : Symbol(Sundries, Decl(typeGuardFunctionOfFormThis.ts, 85, 1))
}
let crate: Crate<{}>;
>crate : Symbol(crate, Decl(typeGuardFunctionOfFormThis.ts, 98, 3))
>Crate : Symbol(Crate, Decl(typeGuardFunctionOfFormThis.ts, 89, 1))
if (crate.isSundries()) {
>crate.isSundries : Symbol(Crate.isSundries, Decl(typeGuardFunctionOfFormThis.ts, 94, 42))
>crate : Symbol(crate, Decl(typeGuardFunctionOfFormThis.ts, 98, 3))
>isSundries : Symbol(Crate.isSundries, Decl(typeGuardFunctionOfFormThis.ts, 94, 42))
crate.contents.broken = true;
>crate.contents.broken : Symbol(Sundries.broken, Decl(typeGuardFunctionOfFormThis.ts, 87, 20))
>crate.contents : Symbol(Crate.contents, Decl(typeGuardFunctionOfFormThis.ts, 91, 20))
>crate : Symbol(crate, Decl(typeGuardFunctionOfFormThis.ts, 98, 3))
>contents : Symbol(Crate.contents, Decl(typeGuardFunctionOfFormThis.ts, 91, 20))
>broken : Symbol(Sundries.broken, Decl(typeGuardFunctionOfFormThis.ts, 87, 20))
}
else if (crate.isSupplies()) {
>crate.isSupplies : Symbol(Crate.isSupplies, Decl(typeGuardFunctionOfFormThis.ts, 93, 19))
>crate : Symbol(crate, Decl(typeGuardFunctionOfFormThis.ts, 98, 3))
>isSupplies : Symbol(Crate.isSupplies, Decl(typeGuardFunctionOfFormThis.ts, 93, 19))
crate.contents.spoiled = true;
>crate.contents.spoiled : Symbol(Supplies.spoiled, Decl(typeGuardFunctionOfFormThis.ts, 83, 20))
>crate.contents : Symbol(Crate.contents, Decl(typeGuardFunctionOfFormThis.ts, 91, 20))
>crate : Symbol(crate, Decl(typeGuardFunctionOfFormThis.ts, 98, 3))
>contents : Symbol(Crate.contents, Decl(typeGuardFunctionOfFormThis.ts, 91, 20))
>spoiled : Symbol(Supplies.spoiled, Decl(typeGuardFunctionOfFormThis.ts, 83, 20))
}
// Matching guards should be assignable
a.isFollower = b.isFollower;
>a.isFollower : Symbol(RoyalGuard.isFollower, Decl(typeGuardFunctionOfFormThis.ts, 3, 5))
>a : Symbol(a, Decl(typeGuardFunctionOfFormThis.ts, 17, 3))
>isFollower : Symbol(RoyalGuard.isFollower, Decl(typeGuardFunctionOfFormThis.ts, 3, 5))
>b.isFollower : Symbol(RoyalGuard.isFollower, Decl(typeGuardFunctionOfFormThis.ts, 3, 5))
>b : Symbol(b, Decl(typeGuardFunctionOfFormThis.ts, 27, 3))
>isFollower : Symbol(RoyalGuard.isFollower, Decl(typeGuardFunctionOfFormThis.ts, 3, 5))
a.isLeader = b.isLeader;
>a.isLeader : Symbol(RoyalGuard.isLeader, Decl(typeGuardFunctionOfFormThis.ts, 0, 18))
>a : Symbol(a, Decl(typeGuardFunctionOfFormThis.ts, 17, 3))
>isLeader : Symbol(RoyalGuard.isLeader, Decl(typeGuardFunctionOfFormThis.ts, 0, 18))
>b.isLeader : Symbol(RoyalGuard.isLeader, Decl(typeGuardFunctionOfFormThis.ts, 0, 18))
>b : Symbol(b, Decl(typeGuardFunctionOfFormThis.ts, 27, 3))
>isLeader : Symbol(RoyalGuard.isLeader, Decl(typeGuardFunctionOfFormThis.ts, 0, 18))
class MimicGuard {
>MimicGuard : Symbol(MimicGuard, Decl(typeGuardFunctionOfFormThis.ts, 110, 24))
isLeader(): this is MimicLeader { return this instanceof MimicLeader; };
>isLeader : Symbol(isLeader, Decl(typeGuardFunctionOfFormThis.ts, 112, 18))
>MimicLeader : Symbol(MimicLeader, Decl(typeGuardFunctionOfFormThis.ts, 115, 1))
>this : Symbol(MimicGuard, Decl(typeGuardFunctionOfFormThis.ts, 110, 24))
>MimicLeader : Symbol(MimicLeader, Decl(typeGuardFunctionOfFormThis.ts, 115, 1))
isFollower(): this is MimicFollower { return this instanceof MimicFollower; };
>isFollower : Symbol(isFollower, Decl(typeGuardFunctionOfFormThis.ts, 113, 76))
>MimicFollower : Symbol(MimicFollower, Decl(typeGuardFunctionOfFormThis.ts, 119, 1))
>this : Symbol(MimicGuard, Decl(typeGuardFunctionOfFormThis.ts, 110, 24))
>MimicFollower : Symbol(MimicFollower, Decl(typeGuardFunctionOfFormThis.ts, 119, 1))
}
class MimicLeader extends MimicGuard {
>MimicLeader : Symbol(MimicLeader, Decl(typeGuardFunctionOfFormThis.ts, 115, 1))
>MimicGuard : Symbol(MimicGuard, Decl(typeGuardFunctionOfFormThis.ts, 110, 24))
lead(): void {}
>lead : Symbol(lead, Decl(typeGuardFunctionOfFormThis.ts, 117, 38))
}
class MimicFollower extends MimicGuard {
>MimicFollower : Symbol(MimicFollower, Decl(typeGuardFunctionOfFormThis.ts, 119, 1))
>MimicGuard : Symbol(MimicGuard, Decl(typeGuardFunctionOfFormThis.ts, 110, 24))
follow(): void {}
>follow : Symbol(follow, Decl(typeGuardFunctionOfFormThis.ts, 121, 40))
}
let mimic = new MimicGuard();
>mimic : Symbol(mimic, Decl(typeGuardFunctionOfFormThis.ts, 125, 3))
>MimicGuard : Symbol(MimicGuard, Decl(typeGuardFunctionOfFormThis.ts, 110, 24))
a.isLeader = mimic.isLeader;
>a.isLeader : Symbol(RoyalGuard.isLeader, Decl(typeGuardFunctionOfFormThis.ts, 0, 18))
>a : Symbol(a, Decl(typeGuardFunctionOfFormThis.ts, 17, 3))
>isLeader : Symbol(RoyalGuard.isLeader, Decl(typeGuardFunctionOfFormThis.ts, 0, 18))
>mimic.isLeader : Symbol(MimicGuard.isLeader, Decl(typeGuardFunctionOfFormThis.ts, 112, 18))
>mimic : Symbol(mimic, Decl(typeGuardFunctionOfFormThis.ts, 125, 3))
>isLeader : Symbol(MimicGuard.isLeader, Decl(typeGuardFunctionOfFormThis.ts, 112, 18))
a.isFollower = mimic.isFollower;
>a.isFollower : Symbol(RoyalGuard.isFollower, Decl(typeGuardFunctionOfFormThis.ts, 3, 5))
>a : Symbol(a, Decl(typeGuardFunctionOfFormThis.ts, 17, 3))
>isFollower : Symbol(RoyalGuard.isFollower, Decl(typeGuardFunctionOfFormThis.ts, 3, 5))
>mimic.isFollower : Symbol(MimicGuard.isFollower, Decl(typeGuardFunctionOfFormThis.ts, 113, 76))
>mimic : Symbol(mimic, Decl(typeGuardFunctionOfFormThis.ts, 125, 3))
>isFollower : Symbol(MimicGuard.isFollower, Decl(typeGuardFunctionOfFormThis.ts, 113, 76))
if (mimic.isFollower()) {
>mimic.isFollower : Symbol(MimicGuard.isFollower, Decl(typeGuardFunctionOfFormThis.ts, 113, 76))
>mimic : Symbol(mimic, Decl(typeGuardFunctionOfFormThis.ts, 125, 3))
>isFollower : Symbol(MimicGuard.isFollower, Decl(typeGuardFunctionOfFormThis.ts, 113, 76))
mimic.follow();
>mimic.follow : Symbol(MimicFollower.follow, Decl(typeGuardFunctionOfFormThis.ts, 121, 40))
>mimic : Symbol(mimic, Decl(typeGuardFunctionOfFormThis.ts, 125, 3))
>follow : Symbol(MimicFollower.follow, Decl(typeGuardFunctionOfFormThis.ts, 121, 40))
mimic.isFollower = a.isFollower;
>mimic.isFollower : Symbol(MimicGuard.isFollower, Decl(typeGuardFunctionOfFormThis.ts, 113, 76))
>mimic : Symbol(mimic, Decl(typeGuardFunctionOfFormThis.ts, 125, 3))
>isFollower : Symbol(MimicGuard.isFollower, Decl(typeGuardFunctionOfFormThis.ts, 113, 76))
>a.isFollower : Symbol(RoyalGuard.isFollower, Decl(typeGuardFunctionOfFormThis.ts, 3, 5))
>a : Symbol(a, Decl(typeGuardFunctionOfFormThis.ts, 17, 3))
>isFollower : Symbol(RoyalGuard.isFollower, Decl(typeGuardFunctionOfFormThis.ts, 3, 5))
}
interface MimicGuardInterface {
>MimicGuardInterface : Symbol(MimicGuardInterface, Decl(typeGuardFunctionOfFormThis.ts, 133, 1))
isLeader(): this is LeadGuard;
>isLeader : Symbol(isLeader, Decl(typeGuardFunctionOfFormThis.ts, 136, 31))
>LeadGuard : Symbol(LeadGuard, Decl(typeGuardFunctionOfFormThis.ts, 7, 1))
isFollower(): this is FollowerGuard;
>isFollower : Symbol(isFollower, Decl(typeGuardFunctionOfFormThis.ts, 137, 34))
>FollowerGuard : Symbol(FollowerGuard, Decl(typeGuardFunctionOfFormThis.ts, 11, 1))
}

View File

@@ -0,0 +1,441 @@
=== tests/cases/conformance/expressions/typeGuards/typeGuardFunctionOfFormThis.ts ===
class RoyalGuard {
>RoyalGuard : RoyalGuard
isLeader(): this is LeadGuard {
>isLeader : () => this is LeadGuard
>LeadGuard : LeadGuard
return this instanceof LeadGuard;
>this instanceof LeadGuard : boolean
>this : this
>LeadGuard : typeof LeadGuard
}
isFollower(): this is FollowerGuard {
>isFollower : () => this is FollowerGuard
>FollowerGuard : FollowerGuard
return this instanceof FollowerGuard;
>this instanceof FollowerGuard : boolean
>this : this
>FollowerGuard : typeof FollowerGuard
}
}
class LeadGuard extends RoyalGuard {
>LeadGuard : LeadGuard
>RoyalGuard : RoyalGuard
lead(): void {};
>lead : () => void
}
class FollowerGuard extends RoyalGuard {
>FollowerGuard : FollowerGuard
>RoyalGuard : RoyalGuard
follow(): void {};
>follow : () => void
}
let a: RoyalGuard = new FollowerGuard();
>a : RoyalGuard
>RoyalGuard : RoyalGuard
>new FollowerGuard() : FollowerGuard
>FollowerGuard : typeof FollowerGuard
if (a.isLeader()) {
>a.isLeader() : this is LeadGuard
>a.isLeader : () => this is LeadGuard
>a : RoyalGuard
>isLeader : () => this is LeadGuard
a.lead();
>a.lead() : void
>a.lead : () => void
>a : LeadGuard
>lead : () => void
}
else if (a.isFollower()) {
>a.isFollower() : this is FollowerGuard
>a.isFollower : () => this is FollowerGuard
>a : RoyalGuard
>isFollower : () => this is FollowerGuard
a.follow();
>a.follow() : void
>a.follow : () => void
>a : FollowerGuard
>follow : () => void
}
interface GuardInterface extends RoyalGuard {}
>GuardInterface : GuardInterface
>RoyalGuard : RoyalGuard
let b: GuardInterface;
>b : GuardInterface
>GuardInterface : GuardInterface
if (b.isLeader()) {
>b.isLeader() : this is LeadGuard
>b.isLeader : () => this is LeadGuard
>b : GuardInterface
>isLeader : () => this is LeadGuard
b.lead();
>b.lead() : void
>b.lead : () => void
>b : LeadGuard
>lead : () => void
}
else if (b.isFollower()) {
>b.isFollower() : this is FollowerGuard
>b.isFollower : () => this is FollowerGuard
>b : GuardInterface
>isFollower : () => this is FollowerGuard
b.follow();
>b.follow() : void
>b.follow : () => void
>b : FollowerGuard
>follow : () => void
}
if (((a.isLeader)())) {
>((a.isLeader)()) : this is LeadGuard
>(a.isLeader)() : this is LeadGuard
>(a.isLeader) : () => this is LeadGuard
>a.isLeader : () => this is LeadGuard
>a : RoyalGuard
>isLeader : () => this is LeadGuard
a.lead();
>a.lead() : void
>a.lead : () => void
>a : LeadGuard
>lead : () => void
}
else if (((a).isFollower())) {
>((a).isFollower()) : this is FollowerGuard
>(a).isFollower() : this is FollowerGuard
>(a).isFollower : () => this is FollowerGuard
>(a) : RoyalGuard
>a : RoyalGuard
>isFollower : () => this is FollowerGuard
a.follow();
>a.follow() : void
>a.follow : () => void
>a : FollowerGuard
>follow : () => void
}
if (((a["isLeader"])())) {
>((a["isLeader"])()) : this is LeadGuard
>(a["isLeader"])() : this is LeadGuard
>(a["isLeader"]) : () => this is LeadGuard
>a["isLeader"] : () => this is LeadGuard
>a : RoyalGuard
>"isLeader" : string
a.lead();
>a.lead() : void
>a.lead : () => void
>a : LeadGuard
>lead : () => void
}
else if (((a)["isFollower"]())) {
>((a)["isFollower"]()) : this is FollowerGuard
>(a)["isFollower"]() : this is FollowerGuard
>(a)["isFollower"] : () => this is FollowerGuard
>(a) : RoyalGuard
>a : RoyalGuard
>"isFollower" : string
a.follow();
>a.follow() : void
>a.follow : () => void
>a : FollowerGuard
>follow : () => void
}
var holder2 = {a};
>holder2 : { a: RoyalGuard; }
>{a} : { a: RoyalGuard; }
>a : RoyalGuard
if (holder2.a.isLeader()) {
>holder2.a.isLeader() : this is LeadGuard
>holder2.a.isLeader : () => this is LeadGuard
>holder2.a : RoyalGuard
>holder2 : { a: RoyalGuard; }
>a : RoyalGuard
>isLeader : () => this is LeadGuard
holder2.a;
>holder2.a : RoyalGuard
>holder2 : { a: RoyalGuard; }
>a : RoyalGuard
}
else {
holder2.a;
>holder2.a : RoyalGuard
>holder2 : { a: RoyalGuard; }
>a : RoyalGuard
}
class ArrowGuard {
>ArrowGuard : ArrowGuard
isElite = (): this is ArrowElite => {
>isElite : () => this is ArrowElite
>(): this is ArrowElite => { return this instanceof ArrowElite; } : () => this is ArrowElite
>ArrowElite : ArrowElite
return this instanceof ArrowElite;
>this instanceof ArrowElite : boolean
>this : this
>ArrowElite : typeof ArrowElite
}
isMedic = (): this is ArrowMedic => {
>isMedic : () => this is ArrowMedic
>(): this is ArrowMedic => { return this instanceof ArrowMedic; } : () => this is ArrowMedic
>ArrowMedic : ArrowMedic
return this instanceof ArrowMedic;
>this instanceof ArrowMedic : boolean
>this : this
>ArrowMedic : typeof ArrowMedic
}
}
class ArrowElite extends ArrowGuard {
>ArrowElite : ArrowElite
>ArrowGuard : ArrowGuard
defend(): void {}
>defend : () => void
}
class ArrowMedic extends ArrowGuard {
>ArrowMedic : ArrowMedic
>ArrowGuard : ArrowGuard
heal(): void {}
>heal : () => void
}
let guard = new ArrowGuard();
>guard : ArrowGuard
>new ArrowGuard() : ArrowGuard
>ArrowGuard : typeof ArrowGuard
if (guard.isElite()) {
>guard.isElite() : this is ArrowElite
>guard.isElite : () => this is ArrowElite
>guard : ArrowGuard
>isElite : () => this is ArrowElite
guard.defend();
>guard.defend() : void
>guard.defend : () => void
>guard : ArrowElite
>defend : () => void
}
else if (guard.isMedic()) {
>guard.isMedic() : this is ArrowMedic
>guard.isMedic : () => this is ArrowMedic
>guard : ArrowGuard
>isMedic : () => this is ArrowMedic
guard.heal();
>guard.heal() : void
>guard.heal : () => void
>guard : ArrowMedic
>heal : () => void
}
interface Supplies {
>Supplies : Supplies
spoiled: boolean;
>spoiled : boolean
}
interface Sundries {
>Sundries : Sundries
broken: boolean;
>broken : boolean
}
interface Crate<T> {
>Crate : Crate<T>
>T : T
contents: T;
>contents : T
>T : T
volume: number;
>volume : number
isSupplies(): this is Crate<Supplies>;
>isSupplies : () => this is Crate<Supplies>
>Crate : Crate<T>
>Supplies : Supplies
isSundries(): this is Crate<Sundries>;
>isSundries : () => this is Crate<Sundries>
>Crate : Crate<T>
>Sundries : Sundries
}
let crate: Crate<{}>;
>crate : Crate<{}>
>Crate : Crate<T>
if (crate.isSundries()) {
>crate.isSundries() : this is Crate<Sundries>
>crate.isSundries : () => this is Crate<Sundries>
>crate : Crate<{}>
>isSundries : () => this is Crate<Sundries>
crate.contents.broken = true;
>crate.contents.broken = true : boolean
>crate.contents.broken : boolean
>crate.contents : Sundries
>crate : Crate<Sundries>
>contents : Sundries
>broken : boolean
>true : boolean
}
else if (crate.isSupplies()) {
>crate.isSupplies() : this is Crate<Supplies>
>crate.isSupplies : () => this is Crate<Supplies>
>crate : Crate<{}>
>isSupplies : () => this is Crate<Supplies>
crate.contents.spoiled = true;
>crate.contents.spoiled = true : boolean
>crate.contents.spoiled : boolean
>crate.contents : Supplies
>crate : Crate<Supplies>
>contents : Supplies
>spoiled : boolean
>true : boolean
}
// Matching guards should be assignable
a.isFollower = b.isFollower;
>a.isFollower = b.isFollower : () => this is FollowerGuard
>a.isFollower : () => this is FollowerGuard
>a : RoyalGuard
>isFollower : () => this is FollowerGuard
>b.isFollower : () => this is FollowerGuard
>b : GuardInterface
>isFollower : () => this is FollowerGuard
a.isLeader = b.isLeader;
>a.isLeader = b.isLeader : () => this is LeadGuard
>a.isLeader : () => this is LeadGuard
>a : RoyalGuard
>isLeader : () => this is LeadGuard
>b.isLeader : () => this is LeadGuard
>b : GuardInterface
>isLeader : () => this is LeadGuard
class MimicGuard {
>MimicGuard : MimicGuard
isLeader(): this is MimicLeader { return this instanceof MimicLeader; };
>isLeader : () => this is MimicLeader
>MimicLeader : MimicLeader
>this instanceof MimicLeader : boolean
>this : this
>MimicLeader : typeof MimicLeader
isFollower(): this is MimicFollower { return this instanceof MimicFollower; };
>isFollower : () => this is MimicFollower
>MimicFollower : MimicFollower
>this instanceof MimicFollower : boolean
>this : this
>MimicFollower : typeof MimicFollower
}
class MimicLeader extends MimicGuard {
>MimicLeader : MimicLeader
>MimicGuard : MimicGuard
lead(): void {}
>lead : () => void
}
class MimicFollower extends MimicGuard {
>MimicFollower : MimicFollower
>MimicGuard : MimicGuard
follow(): void {}
>follow : () => void
}
let mimic = new MimicGuard();
>mimic : MimicGuard
>new MimicGuard() : MimicGuard
>MimicGuard : typeof MimicGuard
a.isLeader = mimic.isLeader;
>a.isLeader = mimic.isLeader : () => this is MimicLeader
>a.isLeader : () => this is LeadGuard
>a : RoyalGuard
>isLeader : () => this is LeadGuard
>mimic.isLeader : () => this is MimicLeader
>mimic : MimicGuard
>isLeader : () => this is MimicLeader
a.isFollower = mimic.isFollower;
>a.isFollower = mimic.isFollower : () => this is MimicFollower
>a.isFollower : () => this is FollowerGuard
>a : RoyalGuard
>isFollower : () => this is FollowerGuard
>mimic.isFollower : () => this is MimicFollower
>mimic : MimicGuard
>isFollower : () => this is MimicFollower
if (mimic.isFollower()) {
>mimic.isFollower() : this is MimicFollower
>mimic.isFollower : () => this is MimicFollower
>mimic : MimicGuard
>isFollower : () => this is MimicFollower
mimic.follow();
>mimic.follow() : void
>mimic.follow : () => void
>mimic : MimicFollower
>follow : () => void
mimic.isFollower = a.isFollower;
>mimic.isFollower = a.isFollower : () => this is FollowerGuard
>mimic.isFollower : () => this is MimicFollower
>mimic : MimicFollower
>isFollower : () => this is MimicFollower
>a.isFollower : () => this is FollowerGuard
>a : RoyalGuard
>isFollower : () => this is FollowerGuard
}
interface MimicGuardInterface {
>MimicGuardInterface : MimicGuardInterface
isLeader(): this is LeadGuard;
>isLeader : () => this is LeadGuard
>LeadGuard : LeadGuard
isFollower(): this is FollowerGuard;
>isFollower : () => this is FollowerGuard
>FollowerGuard : FollowerGuard
}

View File

@@ -0,0 +1,103 @@
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionOfFormThisErrors.ts(23,1): error TS2322: Type '() => this is LeadGuard' is not assignable to type '() => this is FollowerGuard'.
Type predicate 'this is LeadGuard' is not assignable to 'this is FollowerGuard'.
Type 'LeadGuard' is not assignable to type 'FollowerGuard'.
Property 'follow' is missing in type 'LeadGuard'.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionOfFormThisErrors.ts(24,1): error TS2322: Type '() => this is FollowerGuard' is not assignable to type '() => this is LeadGuard'.
Type predicate 'this is FollowerGuard' is not assignable to 'this is LeadGuard'.
Type 'FollowerGuard' is not assignable to type 'LeadGuard'.
Property 'lead' is missing in type 'FollowerGuard'.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionOfFormThisErrors.ts(26,1): error TS2322: Type '() => this is LeadGuard' is not assignable to type '() => this is FollowerGuard'.
Type predicate 'this is LeadGuard' is not assignable to 'this is FollowerGuard'.
Type 'LeadGuard' is not assignable to type 'FollowerGuard'.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionOfFormThisErrors.ts(27,1): error TS2322: Type '() => this is FollowerGuard' is not assignable to type '() => this is LeadGuard'.
Type predicate 'this is FollowerGuard' is not assignable to 'this is LeadGuard'.
Type 'FollowerGuard' is not assignable to type 'LeadGuard'.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionOfFormThisErrors.ts(29,32): error TS2526: A 'this' type is available only in a non-static member of a class or interface.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionOfFormThisErrors.ts(55,7): error TS2339: Property 'follow' does not exist on type 'RoyalGuard'.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionOfFormThisErrors.ts(58,7): error TS2339: Property 'lead' does not exist on type 'RoyalGuard'.
==== tests/cases/conformance/expressions/typeGuards/typeGuardFunctionOfFormThisErrors.ts (7 errors) ====
class RoyalGuard {
isLeader(): this is LeadGuard {
return this instanceof LeadGuard;
}
isFollower(): this is FollowerGuard {
return this instanceof FollowerGuard;
}
}
class LeadGuard extends RoyalGuard {
lead(): void {};
}
class FollowerGuard extends RoyalGuard {
follow(): void {};
}
interface GuardInterface extends RoyalGuard {}
let a: RoyalGuard = new FollowerGuard();
let b: GuardInterface = new LeadGuard();
// Mismatched guards shouldn't be assignable
b.isFollower = b.isLeader;
~~~~~~~~~~~~
!!! error TS2322: Type '() => this is LeadGuard' is not assignable to type '() => this is FollowerGuard'.
!!! error TS2322: Type predicate 'this is LeadGuard' is not assignable to 'this is FollowerGuard'.
!!! error TS2322: Type 'LeadGuard' is not assignable to type 'FollowerGuard'.
!!! error TS2322: Property 'follow' is missing in type 'LeadGuard'.
b.isLeader = b.isFollower;
~~~~~~~~~~
!!! error TS2322: Type '() => this is FollowerGuard' is not assignable to type '() => this is LeadGuard'.
!!! error TS2322: Type predicate 'this is FollowerGuard' is not assignable to 'this is LeadGuard'.
!!! error TS2322: Type 'FollowerGuard' is not assignable to type 'LeadGuard'.
!!! error TS2322: Property 'lead' is missing in type 'FollowerGuard'.
a.isFollower = a.isLeader;
~~~~~~~~~~~~
!!! error TS2322: Type '() => this is LeadGuard' is not assignable to type '() => this is FollowerGuard'.
!!! error TS2322: Type predicate 'this is LeadGuard' is not assignable to 'this is FollowerGuard'.
!!! error TS2322: Type 'LeadGuard' is not assignable to type 'FollowerGuard'.
a.isLeader = a.isFollower;
~~~~~~~~~~
!!! error TS2322: Type '() => this is FollowerGuard' is not assignable to type '() => this is LeadGuard'.
!!! error TS2322: Type predicate 'this is FollowerGuard' is not assignable to 'this is LeadGuard'.
!!! error TS2322: Type 'FollowerGuard' is not assignable to type 'LeadGuard'.
function invalidGuard(c: any): this is number {
~~~~
!!! error TS2526: A 'this' type is available only in a non-static member of a class or interface.
return false;
}
let c: number | number[];
if (invalidGuard(c)) {
c;
}
else {
c;
}
let holder = {invalidGuard};
if (holder.invalidGuard(c)) {
c;
holder;
}
else {
c;
holder;
}
let detached = a.isFollower;
if (detached()) {
a.follow();
~~~~~~
!!! error TS2339: Property 'follow' does not exist on type 'RoyalGuard'.
}
else {
a.lead();
~~~~
!!! error TS2339: Property 'lead' does not exist on type 'RoyalGuard'.
}

View File

@@ -0,0 +1,152 @@
//// [typeGuardFunctionOfFormThisErrors.ts]
class RoyalGuard {
isLeader(): this is LeadGuard {
return this instanceof LeadGuard;
}
isFollower(): this is FollowerGuard {
return this instanceof FollowerGuard;
}
}
class LeadGuard extends RoyalGuard {
lead(): void {};
}
class FollowerGuard extends RoyalGuard {
follow(): void {};
}
interface GuardInterface extends RoyalGuard {}
let a: RoyalGuard = new FollowerGuard();
let b: GuardInterface = new LeadGuard();
// Mismatched guards shouldn't be assignable
b.isFollower = b.isLeader;
b.isLeader = b.isFollower;
a.isFollower = a.isLeader;
a.isLeader = a.isFollower;
function invalidGuard(c: any): this is number {
return false;
}
let c: number | number[];
if (invalidGuard(c)) {
c;
}
else {
c;
}
let holder = {invalidGuard};
if (holder.invalidGuard(c)) {
c;
holder;
}
else {
c;
holder;
}
let detached = a.isFollower;
if (detached()) {
a.follow();
}
else {
a.lead();
}
//// [typeGuardFunctionOfFormThisErrors.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 __());
};
var RoyalGuard = (function () {
function RoyalGuard() {
}
RoyalGuard.prototype.isLeader = function () {
return this instanceof LeadGuard;
};
RoyalGuard.prototype.isFollower = function () {
return this instanceof FollowerGuard;
};
return RoyalGuard;
}());
var LeadGuard = (function (_super) {
__extends(LeadGuard, _super);
function LeadGuard() {
_super.apply(this, arguments);
}
LeadGuard.prototype.lead = function () { };
;
return LeadGuard;
}(RoyalGuard));
var FollowerGuard = (function (_super) {
__extends(FollowerGuard, _super);
function FollowerGuard() {
_super.apply(this, arguments);
}
FollowerGuard.prototype.follow = function () { };
;
return FollowerGuard;
}(RoyalGuard));
var a = new FollowerGuard();
var b = new LeadGuard();
// Mismatched guards shouldn't be assignable
b.isFollower = b.isLeader;
b.isLeader = b.isFollower;
a.isFollower = a.isLeader;
a.isLeader = a.isFollower;
function invalidGuard(c) {
return false;
}
var c;
if (invalidGuard(c)) {
c;
}
else {
c;
}
var holder = { invalidGuard: invalidGuard };
if (holder.invalidGuard(c)) {
c;
holder;
}
else {
c;
holder;
}
var detached = a.isFollower;
if (detached()) {
a.follow();
}
else {
a.lead();
}
//// [typeGuardFunctionOfFormThisErrors.d.ts]
declare class RoyalGuard {
isLeader(): this is LeadGuard;
isFollower(): this is FollowerGuard;
}
declare class LeadGuard extends RoyalGuard {
lead(): void;
}
declare class FollowerGuard extends RoyalGuard {
follow(): void;
}
interface GuardInterface extends RoyalGuard {
}
declare let a: RoyalGuard;
declare let b: GuardInterface;
declare function invalidGuard(c: any): this is number;
declare let c: number | number[];
declare let holder: {
invalidGuard: (c: any) => this is number;
};
declare let detached: () => this is FollowerGuard;

View File

@@ -67,7 +67,7 @@ str = isC1(c1Orc2) && c1Orc2.p1; // C1
>str = isC1(c1Orc2) && c1Orc2.p1 : string
>str : string
>isC1(c1Orc2) && c1Orc2.p1 : string
>isC1(c1Orc2) : boolean
>isC1(c1Orc2) : x is C1
>isC1 : (x: any) => x is C1
>c1Orc2 : C1 | C2
>c1Orc2.p1 : string
@@ -78,7 +78,7 @@ num = isC2(c1Orc2) && c1Orc2.p2; // C2
>num = isC2(c1Orc2) && c1Orc2.p2 : number
>num : number
>isC2(c1Orc2) && c1Orc2.p2 : number
>isC2(c1Orc2) : boolean
>isC2(c1Orc2) : x is C2
>isC2 : (x: any) => x is C2
>c1Orc2 : C1 | C2
>c1Orc2.p2 : number
@@ -89,7 +89,7 @@ str = isD1(c1Orc2) && c1Orc2.p1; // D1
>str = isD1(c1Orc2) && c1Orc2.p1 : string
>str : string
>isD1(c1Orc2) && c1Orc2.p1 : string
>isD1(c1Orc2) : boolean
>isD1(c1Orc2) : x is D1
>isD1 : (x: any) => x is D1
>c1Orc2 : C1 | C2
>c1Orc2.p1 : string
@@ -100,7 +100,7 @@ num = isD1(c1Orc2) && c1Orc2.p3; // D1
>num = isD1(c1Orc2) && c1Orc2.p3 : number
>num : number
>isD1(c1Orc2) && c1Orc2.p3 : number
>isD1(c1Orc2) : boolean
>isD1(c1Orc2) : x is D1
>isD1 : (x: any) => x is D1
>c1Orc2 : C1 | C2
>c1Orc2.p3 : number
@@ -116,7 +116,7 @@ num = isC2(c2Ord1) && c2Ord1.p2; // C2
>num = isC2(c2Ord1) && c2Ord1.p2 : number
>num : number
>isC2(c2Ord1) && c2Ord1.p2 : number
>isC2(c2Ord1) : boolean
>isC2(c2Ord1) : x is C2
>isC2 : (x: any) => x is C2
>c2Ord1 : C2 | D1
>c2Ord1.p2 : number
@@ -127,7 +127,7 @@ num = isD1(c2Ord1) && c2Ord1.p3; // D1
>num = isD1(c2Ord1) && c2Ord1.p3 : number
>num : number
>isD1(c2Ord1) && c2Ord1.p3 : number
>isD1(c2Ord1) : boolean
>isD1(c2Ord1) : x is D1
>isD1 : (x: any) => x is D1
>c2Ord1 : C2 | D1
>c2Ord1.p3 : number
@@ -138,7 +138,7 @@ str = isD1(c2Ord1) && c2Ord1.p1; // D1
>str = isD1(c2Ord1) && c2Ord1.p1 : string
>str : string
>isD1(c2Ord1) && c2Ord1.p1 : string
>isD1(c2Ord1) : boolean
>isD1(c2Ord1) : x is D1
>isD1 : (x: any) => x is D1
>c2Ord1 : C2 | D1
>c2Ord1.p1 : string
@@ -150,7 +150,7 @@ var r2: C2 | D1 = isC1(c2Ord1) && c2Ord1; // C2 | D1
>C2 : C2
>D1 : D1
>isC1(c2Ord1) && c2Ord1 : D1
>isC1(c2Ord1) : boolean
>isC1(c2Ord1) : x is C1
>isC1 : (x: any) => x is C1
>c2Ord1 : C2 | D1
>c2Ord1 : D1

View File

@@ -98,7 +98,7 @@ str = isC1(c1Orc2) && c1Orc2.p1; // C1
>str = isC1(c1Orc2) && c1Orc2.p1 : string
>str : string
>isC1(c1Orc2) && c1Orc2.p1 : string
>isC1(c1Orc2) : boolean
>isC1(c1Orc2) : x is C1
>isC1 : (x: any) => x is C1
>c1Orc2 : C1 | C2
>c1Orc2.p1 : string
@@ -109,7 +109,7 @@ num = isC2(c1Orc2) && c1Orc2.p2; // C2
>num = isC2(c1Orc2) && c1Orc2.p2 : number
>num : number
>isC2(c1Orc2) && c1Orc2.p2 : number
>isC2(c1Orc2) : boolean
>isC2(c1Orc2) : x is C2
>isC2 : (x: any) => x is C2
>c1Orc2 : C1 | C2
>c1Orc2.p2 : number
@@ -120,7 +120,7 @@ str = isD1(c1Orc2) && c1Orc2.p1; // D1
>str = isD1(c1Orc2) && c1Orc2.p1 : string
>str : string
>isD1(c1Orc2) && c1Orc2.p1 : string
>isD1(c1Orc2) : boolean
>isD1(c1Orc2) : x is D1
>isD1 : (x: any) => x is D1
>c1Orc2 : C1 | C2
>c1Orc2.p1 : string
@@ -131,7 +131,7 @@ num = isD1(c1Orc2) && c1Orc2.p3; // D1
>num = isD1(c1Orc2) && c1Orc2.p3 : number
>num : number
>isD1(c1Orc2) && c1Orc2.p3 : number
>isD1(c1Orc2) : boolean
>isD1(c1Orc2) : x is D1
>isD1 : (x: any) => x is D1
>c1Orc2 : C1 | C2
>c1Orc2.p3 : number
@@ -147,7 +147,7 @@ num = isC2(c2Ord1) && c2Ord1.p2; // C2
>num = isC2(c2Ord1) && c2Ord1.p2 : number
>num : number
>isC2(c2Ord1) && c2Ord1.p2 : number
>isC2(c2Ord1) : boolean
>isC2(c2Ord1) : x is C2
>isC2 : (x: any) => x is C2
>c2Ord1 : C2 | D1
>c2Ord1.p2 : number
@@ -158,7 +158,7 @@ num = isD1(c2Ord1) && c2Ord1.p3; // D1
>num = isD1(c2Ord1) && c2Ord1.p3 : number
>num : number
>isD1(c2Ord1) && c2Ord1.p3 : number
>isD1(c2Ord1) : boolean
>isD1(c2Ord1) : x is D1
>isD1 : (x: any) => x is D1
>c2Ord1 : C2 | D1
>c2Ord1.p3 : number
@@ -169,7 +169,7 @@ str = isD1(c2Ord1) && c2Ord1.p1; // D1
>str = isD1(c2Ord1) && c2Ord1.p1 : string
>str : string
>isD1(c2Ord1) && c2Ord1.p1 : string
>isD1(c2Ord1) : boolean
>isD1(c2Ord1) : x is D1
>isD1 : (x: any) => x is D1
>c2Ord1 : C2 | D1
>c2Ord1.p1 : string
@@ -181,7 +181,7 @@ var r2: C2 | D1 = isC1(c2Ord1) && c2Ord1; // C2 | D1
>C2 : C2
>D1 : D1
>isC1(c2Ord1) && c2Ord1 : D1
>isC1(c2Ord1) : boolean
>isC1(c2Ord1) : x is C1
>isC1 : (x: any) => x is C1
>c2Ord1 : C2 | D1
>c2Ord1 : D1

View File

@@ -0,0 +1,187 @@
//// [typeGuardOfFormThisMember.ts]
// There's a 'File' class in the stdlib, wrap with a namespace to avoid collision
namespace Test {
export class FileSystemObject {
isFSO: this is FileSystemObject;
get isFile(): this is File {
return this instanceof File;
}
set isFile(param) {
// noop
}
get isDirectory(): this is Directory {
return this instanceof Directory;
}
isNetworked: this is (Networked & this);
constructor(public path: string) {}
}
export class File extends FileSystemObject {
constructor(path: string, public content: string) { super(path); }
}
export class Directory extends FileSystemObject {
children: FileSystemObject[];
}
export interface Networked {
host: string;
}
let file: FileSystemObject = new File("foo/bar.txt", "foo");
file.isNetworked = false;
file.isFSO = file.isFile;
file.isFile = true;
let x = file.isFile;
if (file.isFile) {
file.content;
if (file.isNetworked) {
file.host;
file.content;
}
}
else if (file.isDirectory) {
file.children;
}
else if (file.isNetworked) {
file.host;
}
interface GenericLeadGuard<T> extends GenericGuard<T> {
lead(): void;
}
interface GenericFollowerGuard<T> extends GenericGuard<T> {
follow(): void;
}
interface GenericGuard<T> {
target: T;
isLeader: this is (GenericLeadGuard<T>);
isFollower: this is GenericFollowerGuard<T>;
}
let guard: GenericGuard<File>;
if (guard.isLeader) {
guard.lead();
}
else if (guard.isFollower) {
guard.follow();
}
interface SpecificGuard {
isMoreSpecific: this is MoreSpecificGuard;
}
interface MoreSpecificGuard extends SpecificGuard {
do(): void;
}
let general: SpecificGuard;
if (general.isMoreSpecific) {
general.do();
}
}
//// [typeGuardOfFormThisMember.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 __());
};
// There's a 'File' class in the stdlib, wrap with a namespace to avoid collision
var Test;
(function (Test) {
var FileSystemObject = (function () {
function FileSystemObject(path) {
this.path = path;
}
Object.defineProperty(FileSystemObject.prototype, "isFile", {
get: function () {
return this instanceof File;
},
set: function (param) {
// noop
},
enumerable: true,
configurable: true
});
Object.defineProperty(FileSystemObject.prototype, "isDirectory", {
get: function () {
return this instanceof Directory;
},
enumerable: true,
configurable: true
});
return FileSystemObject;
}());
Test.FileSystemObject = FileSystemObject;
var File = (function (_super) {
__extends(File, _super);
function File(path, content) {
_super.call(this, path);
this.content = content;
}
return File;
}(FileSystemObject));
Test.File = File;
var Directory = (function (_super) {
__extends(Directory, _super);
function Directory() {
_super.apply(this, arguments);
}
return Directory;
}(FileSystemObject));
Test.Directory = Directory;
var file = new File("foo/bar.txt", "foo");
file.isNetworked = false;
file.isFSO = file.isFile;
file.isFile = true;
var x = file.isFile;
if (file.isFile) {
file.content;
if (file.isNetworked) {
file.host;
file.content;
}
}
else if (file.isDirectory) {
file.children;
}
else if (file.isNetworked) {
file.host;
}
var guard;
if (guard.isLeader) {
guard.lead();
}
else if (guard.isFollower) {
guard.follow();
}
var general;
if (general.isMoreSpecific) {
general.do();
}
})(Test || (Test = {}));
//// [typeGuardOfFormThisMember.d.ts]
declare namespace Test {
class FileSystemObject {
path: string;
isFSO: this is FileSystemObject;
isFile: this is File;
isDirectory: this is Directory;
isNetworked: this is (Networked & this);
constructor(path: string);
}
class File extends FileSystemObject {
content: string;
constructor(path: string, content: string);
}
class Directory extends FileSystemObject {
children: FileSystemObject[];
}
interface Networked {
host: string;
}
}

View File

@@ -0,0 +1,240 @@
=== tests/cases/conformance/expressions/typeGuards/typeGuardOfFormThisMember.ts ===
// There's a 'File' class in the stdlib, wrap with a namespace to avoid collision
namespace Test {
>Test : Symbol(Test, Decl(typeGuardOfFormThisMember.ts, 0, 0))
export class FileSystemObject {
>FileSystemObject : Symbol(FileSystemObject, Decl(typeGuardOfFormThisMember.ts, 1, 16))
isFSO: this is FileSystemObject;
>isFSO : Symbol(isFSO, Decl(typeGuardOfFormThisMember.ts, 2, 32))
>FileSystemObject : Symbol(FileSystemObject, Decl(typeGuardOfFormThisMember.ts, 1, 16))
get isFile(): this is File {
>isFile : Symbol(isFile, Decl(typeGuardOfFormThisMember.ts, 3, 34), Decl(typeGuardOfFormThisMember.ts, 6, 3))
>File : Symbol(File, Decl(typeGuardOfFormThisMember.ts, 15, 2))
return this instanceof File;
>this : Symbol(FileSystemObject, Decl(typeGuardOfFormThisMember.ts, 1, 16))
>File : Symbol(File, Decl(typeGuardOfFormThisMember.ts, 15, 2))
}
set isFile(param) {
>isFile : Symbol(isFile, Decl(typeGuardOfFormThisMember.ts, 3, 34), Decl(typeGuardOfFormThisMember.ts, 6, 3))
>param : Symbol(param, Decl(typeGuardOfFormThisMember.ts, 7, 13))
// noop
}
get isDirectory(): this is Directory {
>isDirectory : Symbol(isDirectory, Decl(typeGuardOfFormThisMember.ts, 9, 3))
>Directory : Symbol(Directory, Decl(typeGuardOfFormThisMember.ts, 19, 2))
return this instanceof Directory;
>this : Symbol(FileSystemObject, Decl(typeGuardOfFormThisMember.ts, 1, 16))
>Directory : Symbol(Directory, Decl(typeGuardOfFormThisMember.ts, 19, 2))
}
isNetworked: this is (Networked & this);
>isNetworked : Symbol(isNetworked, Decl(typeGuardOfFormThisMember.ts, 12, 3))
>Networked : Symbol(Networked, Decl(typeGuardOfFormThisMember.ts, 22, 2))
constructor(public path: string) {}
>path : Symbol(path, Decl(typeGuardOfFormThisMember.ts, 14, 14))
}
export class File extends FileSystemObject {
>File : Symbol(File, Decl(typeGuardOfFormThisMember.ts, 15, 2))
>FileSystemObject : Symbol(FileSystemObject, Decl(typeGuardOfFormThisMember.ts, 1, 16))
constructor(path: string, public content: string) { super(path); }
>path : Symbol(path, Decl(typeGuardOfFormThisMember.ts, 18, 14))
>content : Symbol(content, Decl(typeGuardOfFormThisMember.ts, 18, 27))
>super : Symbol(FileSystemObject, Decl(typeGuardOfFormThisMember.ts, 1, 16))
>path : Symbol(path, Decl(typeGuardOfFormThisMember.ts, 18, 14))
}
export class Directory extends FileSystemObject {
>Directory : Symbol(Directory, Decl(typeGuardOfFormThisMember.ts, 19, 2))
>FileSystemObject : Symbol(FileSystemObject, Decl(typeGuardOfFormThisMember.ts, 1, 16))
children: FileSystemObject[];
>children : Symbol(children, Decl(typeGuardOfFormThisMember.ts, 20, 50))
>FileSystemObject : Symbol(FileSystemObject, Decl(typeGuardOfFormThisMember.ts, 1, 16))
}
export interface Networked {
>Networked : Symbol(Networked, Decl(typeGuardOfFormThisMember.ts, 22, 2))
host: string;
>host : Symbol(host, Decl(typeGuardOfFormThisMember.ts, 23, 29))
}
let file: FileSystemObject = new File("foo/bar.txt", "foo");
>file : Symbol(file, Decl(typeGuardOfFormThisMember.ts, 27, 4))
>FileSystemObject : Symbol(FileSystemObject, Decl(typeGuardOfFormThisMember.ts, 1, 16))
>File : Symbol(File, Decl(typeGuardOfFormThisMember.ts, 15, 2))
file.isNetworked = false;
>file.isNetworked : Symbol(FileSystemObject.isNetworked, Decl(typeGuardOfFormThisMember.ts, 12, 3))
>file : Symbol(file, Decl(typeGuardOfFormThisMember.ts, 27, 4))
>isNetworked : Symbol(FileSystemObject.isNetworked, Decl(typeGuardOfFormThisMember.ts, 12, 3))
file.isFSO = file.isFile;
>file.isFSO : Symbol(FileSystemObject.isFSO, Decl(typeGuardOfFormThisMember.ts, 2, 32))
>file : Symbol(file, Decl(typeGuardOfFormThisMember.ts, 27, 4))
>isFSO : Symbol(FileSystemObject.isFSO, Decl(typeGuardOfFormThisMember.ts, 2, 32))
>file.isFile : Symbol(FileSystemObject.isFile, Decl(typeGuardOfFormThisMember.ts, 3, 34), Decl(typeGuardOfFormThisMember.ts, 6, 3))
>file : Symbol(file, Decl(typeGuardOfFormThisMember.ts, 27, 4))
>isFile : Symbol(FileSystemObject.isFile, Decl(typeGuardOfFormThisMember.ts, 3, 34), Decl(typeGuardOfFormThisMember.ts, 6, 3))
file.isFile = true;
>file.isFile : Symbol(FileSystemObject.isFile, Decl(typeGuardOfFormThisMember.ts, 3, 34), Decl(typeGuardOfFormThisMember.ts, 6, 3))
>file : Symbol(file, Decl(typeGuardOfFormThisMember.ts, 27, 4))
>isFile : Symbol(FileSystemObject.isFile, Decl(typeGuardOfFormThisMember.ts, 3, 34), Decl(typeGuardOfFormThisMember.ts, 6, 3))
let x = file.isFile;
>x : Symbol(x, Decl(typeGuardOfFormThisMember.ts, 31, 4))
>file.isFile : Symbol(FileSystemObject.isFile, Decl(typeGuardOfFormThisMember.ts, 3, 34), Decl(typeGuardOfFormThisMember.ts, 6, 3))
>file : Symbol(file, Decl(typeGuardOfFormThisMember.ts, 27, 4))
>isFile : Symbol(FileSystemObject.isFile, Decl(typeGuardOfFormThisMember.ts, 3, 34), Decl(typeGuardOfFormThisMember.ts, 6, 3))
if (file.isFile) {
>file.isFile : Symbol(FileSystemObject.isFile, Decl(typeGuardOfFormThisMember.ts, 3, 34), Decl(typeGuardOfFormThisMember.ts, 6, 3))
>file : Symbol(file, Decl(typeGuardOfFormThisMember.ts, 27, 4))
>isFile : Symbol(FileSystemObject.isFile, Decl(typeGuardOfFormThisMember.ts, 3, 34), Decl(typeGuardOfFormThisMember.ts, 6, 3))
file.content;
>file.content : Symbol(File.content, Decl(typeGuardOfFormThisMember.ts, 18, 27))
>file : Symbol(file, Decl(typeGuardOfFormThisMember.ts, 27, 4))
>content : Symbol(File.content, Decl(typeGuardOfFormThisMember.ts, 18, 27))
if (file.isNetworked) {
>file.isNetworked : Symbol(FileSystemObject.isNetworked, Decl(typeGuardOfFormThisMember.ts, 12, 3))
>file : Symbol(file, Decl(typeGuardOfFormThisMember.ts, 27, 4))
>isNetworked : Symbol(FileSystemObject.isNetworked, Decl(typeGuardOfFormThisMember.ts, 12, 3))
file.host;
>file.host : Symbol(Networked.host, Decl(typeGuardOfFormThisMember.ts, 23, 29))
>file : Symbol(file, Decl(typeGuardOfFormThisMember.ts, 27, 4))
>host : Symbol(Networked.host, Decl(typeGuardOfFormThisMember.ts, 23, 29))
file.content;
>file.content : Symbol(File.content, Decl(typeGuardOfFormThisMember.ts, 18, 27))
>file : Symbol(file, Decl(typeGuardOfFormThisMember.ts, 27, 4))
>content : Symbol(File.content, Decl(typeGuardOfFormThisMember.ts, 18, 27))
}
}
else if (file.isDirectory) {
>file.isDirectory : Symbol(FileSystemObject.isDirectory, Decl(typeGuardOfFormThisMember.ts, 9, 3))
>file : Symbol(file, Decl(typeGuardOfFormThisMember.ts, 27, 4))
>isDirectory : Symbol(FileSystemObject.isDirectory, Decl(typeGuardOfFormThisMember.ts, 9, 3))
file.children;
>file.children : Symbol(Directory.children, Decl(typeGuardOfFormThisMember.ts, 20, 50))
>file : Symbol(file, Decl(typeGuardOfFormThisMember.ts, 27, 4))
>children : Symbol(Directory.children, Decl(typeGuardOfFormThisMember.ts, 20, 50))
}
else if (file.isNetworked) {
>file.isNetworked : Symbol(FileSystemObject.isNetworked, Decl(typeGuardOfFormThisMember.ts, 12, 3))
>file : Symbol(file, Decl(typeGuardOfFormThisMember.ts, 27, 4))
>isNetworked : Symbol(FileSystemObject.isNetworked, Decl(typeGuardOfFormThisMember.ts, 12, 3))
file.host;
>file.host : Symbol(Networked.host, Decl(typeGuardOfFormThisMember.ts, 23, 29))
>file : Symbol(file, Decl(typeGuardOfFormThisMember.ts, 27, 4))
>host : Symbol(Networked.host, Decl(typeGuardOfFormThisMember.ts, 23, 29))
}
interface GenericLeadGuard<T> extends GenericGuard<T> {
>GenericLeadGuard : Symbol(GenericLeadGuard, Decl(typeGuardOfFormThisMember.ts, 44, 2))
>T : Symbol(T, Decl(typeGuardOfFormThisMember.ts, 46, 28))
>GenericGuard : Symbol(GenericGuard, Decl(typeGuardOfFormThisMember.ts, 52, 2))
>T : Symbol(T, Decl(typeGuardOfFormThisMember.ts, 46, 28))
lead(): void;
>lead : Symbol(lead, Decl(typeGuardOfFormThisMember.ts, 46, 56))
}
interface GenericFollowerGuard<T> extends GenericGuard<T> {
>GenericFollowerGuard : Symbol(GenericFollowerGuard, Decl(typeGuardOfFormThisMember.ts, 48, 2))
>T : Symbol(T, Decl(typeGuardOfFormThisMember.ts, 50, 32))
>GenericGuard : Symbol(GenericGuard, Decl(typeGuardOfFormThisMember.ts, 52, 2))
>T : Symbol(T, Decl(typeGuardOfFormThisMember.ts, 50, 32))
follow(): void;
>follow : Symbol(follow, Decl(typeGuardOfFormThisMember.ts, 50, 60))
}
interface GenericGuard<T> {
>GenericGuard : Symbol(GenericGuard, Decl(typeGuardOfFormThisMember.ts, 52, 2))
>T : Symbol(T, Decl(typeGuardOfFormThisMember.ts, 54, 24))
target: T;
>target : Symbol(target, Decl(typeGuardOfFormThisMember.ts, 54, 28))
>T : Symbol(T, Decl(typeGuardOfFormThisMember.ts, 54, 24))
isLeader: this is (GenericLeadGuard<T>);
>isLeader : Symbol(isLeader, Decl(typeGuardOfFormThisMember.ts, 55, 12))
>GenericLeadGuard : Symbol(GenericLeadGuard, Decl(typeGuardOfFormThisMember.ts, 44, 2))
>T : Symbol(T, Decl(typeGuardOfFormThisMember.ts, 54, 24))
isFollower: this is GenericFollowerGuard<T>;
>isFollower : Symbol(isFollower, Decl(typeGuardOfFormThisMember.ts, 56, 42))
>GenericFollowerGuard : Symbol(GenericFollowerGuard, Decl(typeGuardOfFormThisMember.ts, 48, 2))
>T : Symbol(T, Decl(typeGuardOfFormThisMember.ts, 54, 24))
}
let guard: GenericGuard<File>;
>guard : Symbol(guard, Decl(typeGuardOfFormThisMember.ts, 60, 4))
>GenericGuard : Symbol(GenericGuard, Decl(typeGuardOfFormThisMember.ts, 52, 2))
>File : Symbol(File, Decl(typeGuardOfFormThisMember.ts, 15, 2))
if (guard.isLeader) {
>guard.isLeader : Symbol(GenericGuard.isLeader, Decl(typeGuardOfFormThisMember.ts, 55, 12))
>guard : Symbol(guard, Decl(typeGuardOfFormThisMember.ts, 60, 4))
>isLeader : Symbol(GenericGuard.isLeader, Decl(typeGuardOfFormThisMember.ts, 55, 12))
guard.lead();
>guard.lead : Symbol(GenericLeadGuard.lead, Decl(typeGuardOfFormThisMember.ts, 46, 56))
>guard : Symbol(guard, Decl(typeGuardOfFormThisMember.ts, 60, 4))
>lead : Symbol(GenericLeadGuard.lead, Decl(typeGuardOfFormThisMember.ts, 46, 56))
}
else if (guard.isFollower) {
>guard.isFollower : Symbol(GenericGuard.isFollower, Decl(typeGuardOfFormThisMember.ts, 56, 42))
>guard : Symbol(guard, Decl(typeGuardOfFormThisMember.ts, 60, 4))
>isFollower : Symbol(GenericGuard.isFollower, Decl(typeGuardOfFormThisMember.ts, 56, 42))
guard.follow();
>guard.follow : Symbol(GenericFollowerGuard.follow, Decl(typeGuardOfFormThisMember.ts, 50, 60))
>guard : Symbol(guard, Decl(typeGuardOfFormThisMember.ts, 60, 4))
>follow : Symbol(GenericFollowerGuard.follow, Decl(typeGuardOfFormThisMember.ts, 50, 60))
}
interface SpecificGuard {
>SpecificGuard : Symbol(SpecificGuard, Decl(typeGuardOfFormThisMember.ts, 66, 2))
isMoreSpecific: this is MoreSpecificGuard;
>isMoreSpecific : Symbol(isMoreSpecific, Decl(typeGuardOfFormThisMember.ts, 68, 26))
>MoreSpecificGuard : Symbol(MoreSpecificGuard, Decl(typeGuardOfFormThisMember.ts, 70, 2))
}
interface MoreSpecificGuard extends SpecificGuard {
>MoreSpecificGuard : Symbol(MoreSpecificGuard, Decl(typeGuardOfFormThisMember.ts, 70, 2))
>SpecificGuard : Symbol(SpecificGuard, Decl(typeGuardOfFormThisMember.ts, 66, 2))
do(): void;
>do : Symbol(do, Decl(typeGuardOfFormThisMember.ts, 72, 52))
}
let general: SpecificGuard;
>general : Symbol(general, Decl(typeGuardOfFormThisMember.ts, 76, 4))
>SpecificGuard : Symbol(SpecificGuard, Decl(typeGuardOfFormThisMember.ts, 66, 2))
if (general.isMoreSpecific) {
>general.isMoreSpecific : Symbol(SpecificGuard.isMoreSpecific, Decl(typeGuardOfFormThisMember.ts, 68, 26))
>general : Symbol(general, Decl(typeGuardOfFormThisMember.ts, 76, 4))
>isMoreSpecific : Symbol(SpecificGuard.isMoreSpecific, Decl(typeGuardOfFormThisMember.ts, 68, 26))
general.do();
>general.do : Symbol(MoreSpecificGuard.do, Decl(typeGuardOfFormThisMember.ts, 72, 52))
>general : Symbol(general, Decl(typeGuardOfFormThisMember.ts, 76, 4))
>do : Symbol(MoreSpecificGuard.do, Decl(typeGuardOfFormThisMember.ts, 72, 52))
}
}

View File

@@ -0,0 +1,254 @@
=== tests/cases/conformance/expressions/typeGuards/typeGuardOfFormThisMember.ts ===
// There's a 'File' class in the stdlib, wrap with a namespace to avoid collision
namespace Test {
>Test : typeof Test
export class FileSystemObject {
>FileSystemObject : FileSystemObject
isFSO: this is FileSystemObject;
>isFSO : this is FileSystemObject
>FileSystemObject : FileSystemObject
get isFile(): this is File {
>isFile : this is File
>File : File
return this instanceof File;
>this instanceof File : boolean
>this : this
>File : typeof File
}
set isFile(param) {
>isFile : this is File
>param : boolean
// noop
}
get isDirectory(): this is Directory {
>isDirectory : this is Directory
>Directory : Directory
return this instanceof Directory;
>this instanceof Directory : boolean
>this : this
>Directory : typeof Directory
}
isNetworked: this is (Networked & this);
>isNetworked : this is Networked & this
>Networked : Networked
constructor(public path: string) {}
>path : string
}
export class File extends FileSystemObject {
>File : File
>FileSystemObject : FileSystemObject
constructor(path: string, public content: string) { super(path); }
>path : string
>content : string
>super(path) : void
>super : typeof FileSystemObject
>path : string
}
export class Directory extends FileSystemObject {
>Directory : Directory
>FileSystemObject : FileSystemObject
children: FileSystemObject[];
>children : FileSystemObject[]
>FileSystemObject : FileSystemObject
}
export interface Networked {
>Networked : Networked
host: string;
>host : string
}
let file: FileSystemObject = new File("foo/bar.txt", "foo");
>file : FileSystemObject
>FileSystemObject : FileSystemObject
>new File("foo/bar.txt", "foo") : File
>File : typeof File
>"foo/bar.txt" : string
>"foo" : string
file.isNetworked = false;
>file.isNetworked = false : boolean
>file.isNetworked : this is Networked & FileSystemObject
>file : FileSystemObject
>isNetworked : this is Networked & FileSystemObject
>false : boolean
file.isFSO = file.isFile;
>file.isFSO = file.isFile : this is File
>file.isFSO : this is FileSystemObject
>file : FileSystemObject
>isFSO : this is FileSystemObject
>file.isFile : this is File
>file : FileSystemObject
>isFile : this is File
file.isFile = true;
>file.isFile = true : boolean
>file.isFile : this is File
>file : FileSystemObject
>isFile : this is File
>true : boolean
let x = file.isFile;
>x : boolean
>file.isFile : this is File
>file : FileSystemObject
>isFile : this is File
if (file.isFile) {
>file.isFile : this is File
>file : FileSystemObject
>isFile : this is File
file.content;
>file.content : string
>file : File
>content : string
if (file.isNetworked) {
>file.isNetworked : this is Networked & File
>file : File
>isNetworked : this is Networked & File
file.host;
>file.host : string
>file : Networked & File
>host : string
file.content;
>file.content : string
>file : Networked & File
>content : string
}
}
else if (file.isDirectory) {
>file.isDirectory : this is Directory
>file : FileSystemObject
>isDirectory : this is Directory
file.children;
>file.children : FileSystemObject[]
>file : Directory
>children : FileSystemObject[]
}
else if (file.isNetworked) {
>file.isNetworked : this is Networked & FileSystemObject
>file : FileSystemObject
>isNetworked : this is Networked & FileSystemObject
file.host;
>file.host : string
>file : Networked & FileSystemObject
>host : string
}
interface GenericLeadGuard<T> extends GenericGuard<T> {
>GenericLeadGuard : GenericLeadGuard<T>
>T : T
>GenericGuard : GenericGuard<T>
>T : T
lead(): void;
>lead : () => void
}
interface GenericFollowerGuard<T> extends GenericGuard<T> {
>GenericFollowerGuard : GenericFollowerGuard<T>
>T : T
>GenericGuard : GenericGuard<T>
>T : T
follow(): void;
>follow : () => void
}
interface GenericGuard<T> {
>GenericGuard : GenericGuard<T>
>T : T
target: T;
>target : T
>T : T
isLeader: this is (GenericLeadGuard<T>);
>isLeader : this is GenericLeadGuard<T>
>GenericLeadGuard : GenericLeadGuard<T>
>T : T
isFollower: this is GenericFollowerGuard<T>;
>isFollower : this is GenericFollowerGuard<T>
>GenericFollowerGuard : GenericFollowerGuard<T>
>T : T
}
let guard: GenericGuard<File>;
>guard : GenericGuard<File>
>GenericGuard : GenericGuard<T>
>File : File
if (guard.isLeader) {
>guard.isLeader : this is GenericLeadGuard<File>
>guard : GenericGuard<File>
>isLeader : this is GenericLeadGuard<File>
guard.lead();
>guard.lead() : void
>guard.lead : () => void
>guard : GenericLeadGuard<File>
>lead : () => void
}
else if (guard.isFollower) {
>guard.isFollower : this is GenericFollowerGuard<File>
>guard : GenericGuard<File>
>isFollower : this is GenericFollowerGuard<File>
guard.follow();
>guard.follow() : void
>guard.follow : () => void
>guard : GenericFollowerGuard<File>
>follow : () => void
}
interface SpecificGuard {
>SpecificGuard : SpecificGuard
isMoreSpecific: this is MoreSpecificGuard;
>isMoreSpecific : this is MoreSpecificGuard
>MoreSpecificGuard : MoreSpecificGuard
}
interface MoreSpecificGuard extends SpecificGuard {
>MoreSpecificGuard : MoreSpecificGuard
>SpecificGuard : SpecificGuard
do(): void;
>do : () => void
}
let general: SpecificGuard;
>general : SpecificGuard
>SpecificGuard : SpecificGuard
if (general.isMoreSpecific) {
>general.isMoreSpecific : this is MoreSpecificGuard
>general : SpecificGuard
>isMoreSpecific : this is MoreSpecificGuard
general.do();
>general.do() : void
>general.do : () => void
>general : MoreSpecificGuard
>do : () => void
}
}

View File

@@ -0,0 +1,51 @@
tests/cases/conformance/expressions/typeGuards/typeGuardOfFormThisMemberErrors.ts(29,2): error TS1226: Type predicate 'this is File' is not assignable to 'this is Networked & FileSystemObject'.
Type 'File' is not assignable to type 'Networked & FileSystemObject'.
Type 'File' is not assignable to type 'Networked'.
Property 'host' is missing in type 'File'.
tests/cases/conformance/expressions/typeGuards/typeGuardOfFormThisMemberErrors.ts(31,2): error TS1226: Type predicate 'this is FileSystemObject' is not assignable to 'this is File'.
Type 'FileSystemObject' is not assignable to type 'File'.
Property 'content' is missing in type 'FileSystemObject'.
==== tests/cases/conformance/expressions/typeGuards/typeGuardOfFormThisMemberErrors.ts (2 errors) ====
// There's a 'File' class in the stdlib, wrap with a namespace to avoid collision
namespace Test {
export class FileSystemObject {
isFSO: this is FileSystemObject;
get isFile(): this is File {
return this instanceof File;
}
set isFile(param) {
// noop
}
get isDirectory(): this is Directory {
return this instanceof Directory;
}
isNetworked: this is (Networked & this);
constructor(public path: string) {}
}
export class File extends FileSystemObject {
constructor(path: string, public content: string) { super(path); }
}
export class Directory extends FileSystemObject {
children: FileSystemObject[];
}
export interface Networked {
host: string;
}
let file: FileSystemObject = new File("foo/bar.txt", "foo");
file.isNetworked = file.isFile;
~~~~~~~~~~~~~~~~
!!! error TS1226: Type predicate 'this is File' is not assignable to 'this is Networked & FileSystemObject'.
!!! error TS1226: Type 'File' is not assignable to type 'Networked & FileSystemObject'.
!!! error TS1226: Type 'File' is not assignable to type 'Networked'.
!!! error TS1226: Property 'host' is missing in type 'File'.
file.isFSO = file.isNetworked;
file.isFile = file.isFSO;
~~~~~~~~~~~
!!! error TS1226: Type predicate 'this is FileSystemObject' is not assignable to 'this is File'.
!!! error TS1226: Type 'FileSystemObject' is not assignable to type 'File'.
!!! error TS1226: Property 'content' is missing in type 'FileSystemObject'.
}

View File

@@ -0,0 +1,112 @@
//// [typeGuardOfFormThisMemberErrors.ts]
// There's a 'File' class in the stdlib, wrap with a namespace to avoid collision
namespace Test {
export class FileSystemObject {
isFSO: this is FileSystemObject;
get isFile(): this is File {
return this instanceof File;
}
set isFile(param) {
// noop
}
get isDirectory(): this is Directory {
return this instanceof Directory;
}
isNetworked: this is (Networked & this);
constructor(public path: string) {}
}
export class File extends FileSystemObject {
constructor(path: string, public content: string) { super(path); }
}
export class Directory extends FileSystemObject {
children: FileSystemObject[];
}
export interface Networked {
host: string;
}
let file: FileSystemObject = new File("foo/bar.txt", "foo");
file.isNetworked = file.isFile;
file.isFSO = file.isNetworked;
file.isFile = file.isFSO;
}
//// [typeGuardOfFormThisMemberErrors.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 __());
};
// There's a 'File' class in the stdlib, wrap with a namespace to avoid collision
var Test;
(function (Test) {
var FileSystemObject = (function () {
function FileSystemObject(path) {
this.path = path;
}
Object.defineProperty(FileSystemObject.prototype, "isFile", {
get: function () {
return this instanceof File;
},
set: function (param) {
// noop
},
enumerable: true,
configurable: true
});
Object.defineProperty(FileSystemObject.prototype, "isDirectory", {
get: function () {
return this instanceof Directory;
},
enumerable: true,
configurable: true
});
return FileSystemObject;
}());
Test.FileSystemObject = FileSystemObject;
var File = (function (_super) {
__extends(File, _super);
function File(path, content) {
_super.call(this, path);
this.content = content;
}
return File;
}(FileSystemObject));
Test.File = File;
var Directory = (function (_super) {
__extends(Directory, _super);
function Directory() {
_super.apply(this, arguments);
}
return Directory;
}(FileSystemObject));
Test.Directory = Directory;
var file = new File("foo/bar.txt", "foo");
file.isNetworked = file.isFile;
file.isFSO = file.isNetworked;
file.isFile = file.isFSO;
})(Test || (Test = {}));
//// [typeGuardOfFormThisMemberErrors.d.ts]
declare namespace Test {
class FileSystemObject {
path: string;
isFSO: this is FileSystemObject;
isFile: this is File;
isDirectory: this is Directory;
isNetworked: this is (Networked & this);
constructor(path: string);
}
class File extends FileSystemObject {
content: string;
constructor(path: string, content: string);
}
class Directory extends FileSystemObject {
children: FileSystemObject[];
}
interface Networked {
host: string;
}
}

View File

@@ -110,7 +110,7 @@ function foo1<a>(value: void|a): void {
>a : a
if (isVoid(value)) {
>isVoid(value) : boolean
>isVoid(value) : value is void
>isVoid : <a>(value: void | a) => value is void
>value : void | a
@@ -130,7 +130,7 @@ function baz1<a>(value: void|a): void {
>a : a
if (isNonVoid(value)) {
>isNonVoid(value) : boolean
>isNonVoid(value) : value is a
>isNonVoid : <a>(value: void | a) => value is a
>value : void | a

View File

@@ -0,0 +1,141 @@
// @declaration: true
class RoyalGuard {
isLeader(): this is LeadGuard {
return this instanceof LeadGuard;
}
isFollower(): this is FollowerGuard {
return this instanceof FollowerGuard;
}
}
class LeadGuard extends RoyalGuard {
lead(): void {};
}
class FollowerGuard extends RoyalGuard {
follow(): void {};
}
let a: RoyalGuard = new FollowerGuard();
if (a.isLeader()) {
a.lead();
}
else if (a.isFollower()) {
a.follow();
}
interface GuardInterface extends RoyalGuard {}
let b: GuardInterface;
if (b.isLeader()) {
b.lead();
}
else if (b.isFollower()) {
b.follow();
}
if (((a.isLeader)())) {
a.lead();
}
else if (((a).isFollower())) {
a.follow();
}
if (((a["isLeader"])())) {
a.lead();
}
else if (((a)["isFollower"]())) {
a.follow();
}
var holder2 = {a};
if (holder2.a.isLeader()) {
holder2.a;
}
else {
holder2.a;
}
class ArrowGuard {
isElite = (): this is ArrowElite => {
return this instanceof ArrowElite;
}
isMedic = (): this is ArrowMedic => {
return this instanceof ArrowMedic;
}
}
class ArrowElite extends ArrowGuard {
defend(): void {}
}
class ArrowMedic extends ArrowGuard {
heal(): void {}
}
let guard = new ArrowGuard();
if (guard.isElite()) {
guard.defend();
}
else if (guard.isMedic()) {
guard.heal();
}
interface Supplies {
spoiled: boolean;
}
interface Sundries {
broken: boolean;
}
interface Crate<T> {
contents: T;
volume: number;
isSupplies(): this is Crate<Supplies>;
isSundries(): this is Crate<Sundries>;
}
let crate: Crate<{}>;
if (crate.isSundries()) {
crate.contents.broken = true;
}
else if (crate.isSupplies()) {
crate.contents.spoiled = true;
}
// Matching guards should be assignable
a.isFollower = b.isFollower;
a.isLeader = b.isLeader;
class MimicGuard {
isLeader(): this is MimicLeader { return this instanceof MimicLeader; };
isFollower(): this is MimicFollower { return this instanceof MimicFollower; };
}
class MimicLeader extends MimicGuard {
lead(): void {}
}
class MimicFollower extends MimicGuard {
follow(): void {}
}
let mimic = new MimicGuard();
a.isLeader = mimic.isLeader;
a.isFollower = mimic.isFollower;
if (mimic.isFollower()) {
mimic.follow();
mimic.isFollower = a.isFollower;
}
interface MimicGuardInterface {
isLeader(): this is LeadGuard;
isFollower(): this is FollowerGuard;
}

View File

@@ -0,0 +1,60 @@
// @declaration: true
class RoyalGuard {
isLeader(): this is LeadGuard {
return this instanceof LeadGuard;
}
isFollower(): this is FollowerGuard {
return this instanceof FollowerGuard;
}
}
class LeadGuard extends RoyalGuard {
lead(): void {};
}
class FollowerGuard extends RoyalGuard {
follow(): void {};
}
interface GuardInterface extends RoyalGuard {}
let a: RoyalGuard = new FollowerGuard();
let b: GuardInterface = new LeadGuard();
// Mismatched guards shouldn't be assignable
b.isFollower = b.isLeader;
b.isLeader = b.isFollower;
a.isFollower = a.isLeader;
a.isLeader = a.isFollower;
function invalidGuard(c: any): this is number {
return false;
}
let c: number | number[];
if (invalidGuard(c)) {
c;
}
else {
c;
}
let holder = {invalidGuard};
if (holder.invalidGuard(c)) {
c;
holder;
}
else {
c;
holder;
}
let detached = a.isFollower;
if (detached()) {
a.follow();
}
else {
a.lead();
}

View File

@@ -0,0 +1,83 @@
// @target: es5
// @declaration: true
// There's a 'File' class in the stdlib, wrap with a namespace to avoid collision
namespace Test {
export class FileSystemObject {
isFSO: this is FileSystemObject;
get isFile(): this is File {
return this instanceof File;
}
set isFile(param) {
// noop
}
get isDirectory(): this is Directory {
return this instanceof Directory;
}
isNetworked: this is (Networked & this);
constructor(public path: string) {}
}
export class File extends FileSystemObject {
constructor(path: string, public content: string) { super(path); }
}
export class Directory extends FileSystemObject {
children: FileSystemObject[];
}
export interface Networked {
host: string;
}
let file: FileSystemObject = new File("foo/bar.txt", "foo");
file.isNetworked = false;
file.isFSO = file.isFile;
file.isFile = true;
let x = file.isFile;
if (file.isFile) {
file.content;
if (file.isNetworked) {
file.host;
file.content;
}
}
else if (file.isDirectory) {
file.children;
}
else if (file.isNetworked) {
file.host;
}
interface GenericLeadGuard<T> extends GenericGuard<T> {
lead(): void;
}
interface GenericFollowerGuard<T> extends GenericGuard<T> {
follow(): void;
}
interface GenericGuard<T> {
target: T;
isLeader: this is (GenericLeadGuard<T>);
isFollower: this is GenericFollowerGuard<T>;
}
let guard: GenericGuard<File>;
if (guard.isLeader) {
guard.lead();
}
else if (guard.isFollower) {
guard.follow();
}
interface SpecificGuard {
isMoreSpecific: this is MoreSpecificGuard;
}
interface MoreSpecificGuard extends SpecificGuard {
do(): void;
}
let general: SpecificGuard;
if (general.isMoreSpecific) {
general.do();
}
}

View File

@@ -0,0 +1,34 @@
// @target: es5
// @declaration: true
// There's a 'File' class in the stdlib, wrap with a namespace to avoid collision
namespace Test {
export class FileSystemObject {
isFSO: this is FileSystemObject;
get isFile(): this is File {
return this instanceof File;
}
set isFile(param) {
// noop
}
get isDirectory(): this is Directory {
return this instanceof Directory;
}
isNetworked: this is (Networked & this);
constructor(public path: string) {}
}
export class File extends FileSystemObject {
constructor(path: string, public content: string) { super(path); }
}
export class Directory extends FileSystemObject {
children: FileSystemObject[];
}
export interface Networked {
host: string;
}
let file: FileSystemObject = new File("foo/bar.txt", "foo");
file.isNetworked = file.isFile;
file.isFSO = file.isNetworked;
file.isFile = file.isFSO;
}