mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-17 01:49:57 -05:00
Add tests
This commit is contained in:
181
tests/baselines/reference/typeGuardIntersectionTypes.js
Normal file
181
tests/baselines/reference/typeGuardIntersectionTypes.js
Normal file
@@ -0,0 +1,181 @@
|
||||
//// [typeGuardIntersectionTypes.ts]
|
||||
|
||||
interface X {
|
||||
x: string;
|
||||
}
|
||||
|
||||
interface Y {
|
||||
y: string;
|
||||
}
|
||||
|
||||
interface Z {
|
||||
z: string;
|
||||
}
|
||||
|
||||
declare function isX(obj: any): obj is X;
|
||||
declare function isY(obj: any): obj is Y;
|
||||
declare function isZ(obj: any): obj is Z;
|
||||
|
||||
function f1(obj: Object) {
|
||||
if (isX(obj) || isY(obj) || isZ(obj)) {
|
||||
obj;
|
||||
}
|
||||
if (isX(obj) && isY(obj) && isZ(obj)) {
|
||||
obj;
|
||||
}
|
||||
}
|
||||
|
||||
// Repro from #8911
|
||||
|
||||
// two interfaces
|
||||
interface A {
|
||||
a: string;
|
||||
}
|
||||
|
||||
interface B {
|
||||
b: string;
|
||||
}
|
||||
|
||||
// a type guard for B
|
||||
function isB(toTest: any): toTest is B {
|
||||
return toTest && toTest.b;
|
||||
}
|
||||
|
||||
// a function that turns an A into an A & B
|
||||
function union(a: A): A & B | null {
|
||||
if (isB(a)) {
|
||||
return a;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Repro from #9011
|
||||
|
||||
declare function log(s: string): void;
|
||||
|
||||
// Supported beast features
|
||||
interface Beast { wings?: boolean; legs?: number }
|
||||
interface Legged { legs: number; }
|
||||
interface Winged { wings: boolean; }
|
||||
|
||||
// Beast feature detection via user-defined type guards
|
||||
function hasLegs(x: Beast): x is Legged { return x && typeof x.legs === 'number'; }
|
||||
function hasWings(x: Beast): x is Winged { return x && !!x.wings; }
|
||||
|
||||
// Function to identify a given beast by detecting its features
|
||||
function identifyBeast(beast: Beast) {
|
||||
|
||||
// All beasts with legs
|
||||
if (hasLegs(beast)) {
|
||||
|
||||
// All winged beasts with legs
|
||||
if (hasWings(beast)) {
|
||||
if (beast.legs === 4) { // ERROR TS2339: Property 'legs' does not exist on type 'Winged'.
|
||||
log(`pegasus - 4 legs, wings`);
|
||||
}
|
||||
else if (beast.legs === 2) { // ERROR TS2339...
|
||||
log(`bird - 2 legs, wings`);
|
||||
}
|
||||
else {
|
||||
log(`unknown - ${beast.legs} legs, wings`); // ERROR TS2339...
|
||||
}
|
||||
}
|
||||
|
||||
// All non-winged beasts with legs
|
||||
else {
|
||||
log(`manbearpig - ${beast.legs} legs, no wings`);
|
||||
}
|
||||
}
|
||||
|
||||
// All beasts without legs
|
||||
else {
|
||||
if (hasWings(beast)) {
|
||||
log(`quetzalcoatl - no legs, wings`)
|
||||
}
|
||||
else {
|
||||
log(`snake - no legs, no wings`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function beastFoo(beast: Object) {
|
||||
if (hasWings(beast) && hasLegs(beast)) {
|
||||
beast // beast is Legged
|
||||
// ideally, beast would be Winged && Legged here...
|
||||
}
|
||||
else {
|
||||
beast
|
||||
}
|
||||
|
||||
if (hasLegs(beast) && hasWings(beast)) {
|
||||
beast // beast is Winged
|
||||
// ideally, beast would be Legged && Winged here...
|
||||
}
|
||||
}
|
||||
|
||||
//// [typeGuardIntersectionTypes.js]
|
||||
function f1(obj) {
|
||||
if (isX(obj) || isY(obj) || isZ(obj)) {
|
||||
obj;
|
||||
}
|
||||
if (isX(obj) && isY(obj) && isZ(obj)) {
|
||||
obj;
|
||||
}
|
||||
}
|
||||
// a type guard for B
|
||||
function isB(toTest) {
|
||||
return toTest && toTest.b;
|
||||
}
|
||||
// a function that turns an A into an A & B
|
||||
function union(a) {
|
||||
if (isB(a)) {
|
||||
return a;
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
// Beast feature detection via user-defined type guards
|
||||
function hasLegs(x) { return x && typeof x.legs === 'number'; }
|
||||
function hasWings(x) { return x && !!x.wings; }
|
||||
// Function to identify a given beast by detecting its features
|
||||
function identifyBeast(beast) {
|
||||
// All beasts with legs
|
||||
if (hasLegs(beast)) {
|
||||
// All winged beasts with legs
|
||||
if (hasWings(beast)) {
|
||||
if (beast.legs === 4) {
|
||||
log("pegasus - 4 legs, wings");
|
||||
}
|
||||
else if (beast.legs === 2) {
|
||||
log("bird - 2 legs, wings");
|
||||
}
|
||||
else {
|
||||
log("unknown - " + beast.legs + " legs, wings"); // ERROR TS2339...
|
||||
}
|
||||
}
|
||||
else {
|
||||
log("manbearpig - " + beast.legs + " legs, no wings");
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (hasWings(beast)) {
|
||||
log("quetzalcoatl - no legs, wings");
|
||||
}
|
||||
else {
|
||||
log("snake - no legs, no wings");
|
||||
}
|
||||
}
|
||||
}
|
||||
function beastFoo(beast) {
|
||||
if (hasWings(beast) && hasLegs(beast)) {
|
||||
beast; // beast is Legged
|
||||
}
|
||||
else {
|
||||
beast;
|
||||
}
|
||||
if (hasLegs(beast) && hasWings(beast)) {
|
||||
beast; // beast is Winged
|
||||
}
|
||||
}
|
||||
262
tests/baselines/reference/typeGuardIntersectionTypes.symbols
Normal file
262
tests/baselines/reference/typeGuardIntersectionTypes.symbols
Normal file
@@ -0,0 +1,262 @@
|
||||
=== tests/cases/conformance/expressions/typeGuards/typeGuardIntersectionTypes.ts ===
|
||||
|
||||
interface X {
|
||||
>X : Symbol(X, Decl(typeGuardIntersectionTypes.ts, 0, 0))
|
||||
|
||||
x: string;
|
||||
>x : Symbol(X.x, Decl(typeGuardIntersectionTypes.ts, 1, 13))
|
||||
}
|
||||
|
||||
interface Y {
|
||||
>Y : Symbol(Y, Decl(typeGuardIntersectionTypes.ts, 3, 1))
|
||||
|
||||
y: string;
|
||||
>y : Symbol(Y.y, Decl(typeGuardIntersectionTypes.ts, 5, 13))
|
||||
}
|
||||
|
||||
interface Z {
|
||||
>Z : Symbol(Z, Decl(typeGuardIntersectionTypes.ts, 7, 1))
|
||||
|
||||
z: string;
|
||||
>z : Symbol(Z.z, Decl(typeGuardIntersectionTypes.ts, 9, 13))
|
||||
}
|
||||
|
||||
declare function isX(obj: any): obj is X;
|
||||
>isX : Symbol(isX, Decl(typeGuardIntersectionTypes.ts, 11, 1))
|
||||
>obj : Symbol(obj, Decl(typeGuardIntersectionTypes.ts, 13, 21))
|
||||
>obj : Symbol(obj, Decl(typeGuardIntersectionTypes.ts, 13, 21))
|
||||
>X : Symbol(X, Decl(typeGuardIntersectionTypes.ts, 0, 0))
|
||||
|
||||
declare function isY(obj: any): obj is Y;
|
||||
>isY : Symbol(isY, Decl(typeGuardIntersectionTypes.ts, 13, 41))
|
||||
>obj : Symbol(obj, Decl(typeGuardIntersectionTypes.ts, 14, 21))
|
||||
>obj : Symbol(obj, Decl(typeGuardIntersectionTypes.ts, 14, 21))
|
||||
>Y : Symbol(Y, Decl(typeGuardIntersectionTypes.ts, 3, 1))
|
||||
|
||||
declare function isZ(obj: any): obj is Z;
|
||||
>isZ : Symbol(isZ, Decl(typeGuardIntersectionTypes.ts, 14, 41))
|
||||
>obj : Symbol(obj, Decl(typeGuardIntersectionTypes.ts, 15, 21))
|
||||
>obj : Symbol(obj, Decl(typeGuardIntersectionTypes.ts, 15, 21))
|
||||
>Z : Symbol(Z, Decl(typeGuardIntersectionTypes.ts, 7, 1))
|
||||
|
||||
function f1(obj: Object) {
|
||||
>f1 : Symbol(f1, Decl(typeGuardIntersectionTypes.ts, 15, 41))
|
||||
>obj : Symbol(obj, Decl(typeGuardIntersectionTypes.ts, 17, 12))
|
||||
>Object : Symbol(Object, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
|
||||
if (isX(obj) || isY(obj) || isZ(obj)) {
|
||||
>isX : Symbol(isX, Decl(typeGuardIntersectionTypes.ts, 11, 1))
|
||||
>obj : Symbol(obj, Decl(typeGuardIntersectionTypes.ts, 17, 12))
|
||||
>isY : Symbol(isY, Decl(typeGuardIntersectionTypes.ts, 13, 41))
|
||||
>obj : Symbol(obj, Decl(typeGuardIntersectionTypes.ts, 17, 12))
|
||||
>isZ : Symbol(isZ, Decl(typeGuardIntersectionTypes.ts, 14, 41))
|
||||
>obj : Symbol(obj, Decl(typeGuardIntersectionTypes.ts, 17, 12))
|
||||
|
||||
obj;
|
||||
>obj : Symbol(obj, Decl(typeGuardIntersectionTypes.ts, 17, 12))
|
||||
}
|
||||
if (isX(obj) && isY(obj) && isZ(obj)) {
|
||||
>isX : Symbol(isX, Decl(typeGuardIntersectionTypes.ts, 11, 1))
|
||||
>obj : Symbol(obj, Decl(typeGuardIntersectionTypes.ts, 17, 12))
|
||||
>isY : Symbol(isY, Decl(typeGuardIntersectionTypes.ts, 13, 41))
|
||||
>obj : Symbol(obj, Decl(typeGuardIntersectionTypes.ts, 17, 12))
|
||||
>isZ : Symbol(isZ, Decl(typeGuardIntersectionTypes.ts, 14, 41))
|
||||
>obj : Symbol(obj, Decl(typeGuardIntersectionTypes.ts, 17, 12))
|
||||
|
||||
obj;
|
||||
>obj : Symbol(obj, Decl(typeGuardIntersectionTypes.ts, 17, 12))
|
||||
}
|
||||
}
|
||||
|
||||
// Repro from #8911
|
||||
|
||||
// two interfaces
|
||||
interface A {
|
||||
>A : Symbol(A, Decl(typeGuardIntersectionTypes.ts, 24, 1))
|
||||
|
||||
a: string;
|
||||
>a : Symbol(A.a, Decl(typeGuardIntersectionTypes.ts, 29, 13))
|
||||
}
|
||||
|
||||
interface B {
|
||||
>B : Symbol(B, Decl(typeGuardIntersectionTypes.ts, 31, 1))
|
||||
|
||||
b: string;
|
||||
>b : Symbol(B.b, Decl(typeGuardIntersectionTypes.ts, 33, 13))
|
||||
}
|
||||
|
||||
// a type guard for B
|
||||
function isB(toTest: any): toTest is B {
|
||||
>isB : Symbol(isB, Decl(typeGuardIntersectionTypes.ts, 35, 1))
|
||||
>toTest : Symbol(toTest, Decl(typeGuardIntersectionTypes.ts, 38, 13))
|
||||
>toTest : Symbol(toTest, Decl(typeGuardIntersectionTypes.ts, 38, 13))
|
||||
>B : Symbol(B, Decl(typeGuardIntersectionTypes.ts, 31, 1))
|
||||
|
||||
return toTest && toTest.b;
|
||||
>toTest : Symbol(toTest, Decl(typeGuardIntersectionTypes.ts, 38, 13))
|
||||
>toTest : Symbol(toTest, Decl(typeGuardIntersectionTypes.ts, 38, 13))
|
||||
}
|
||||
|
||||
// a function that turns an A into an A & B
|
||||
function union(a: A): A & B | null {
|
||||
>union : Symbol(union, Decl(typeGuardIntersectionTypes.ts, 40, 1))
|
||||
>a : Symbol(a, Decl(typeGuardIntersectionTypes.ts, 43, 15))
|
||||
>A : Symbol(A, Decl(typeGuardIntersectionTypes.ts, 24, 1))
|
||||
>A : Symbol(A, Decl(typeGuardIntersectionTypes.ts, 24, 1))
|
||||
>B : Symbol(B, Decl(typeGuardIntersectionTypes.ts, 31, 1))
|
||||
|
||||
if (isB(a)) {
|
||||
>isB : Symbol(isB, Decl(typeGuardIntersectionTypes.ts, 35, 1))
|
||||
>a : Symbol(a, Decl(typeGuardIntersectionTypes.ts, 43, 15))
|
||||
|
||||
return a;
|
||||
>a : Symbol(a, Decl(typeGuardIntersectionTypes.ts, 43, 15))
|
||||
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Repro from #9011
|
||||
|
||||
declare function log(s: string): void;
|
||||
>log : Symbol(log, Decl(typeGuardIntersectionTypes.ts, 49, 1))
|
||||
>s : Symbol(s, Decl(typeGuardIntersectionTypes.ts, 53, 21))
|
||||
|
||||
// Supported beast features
|
||||
interface Beast { wings?: boolean; legs?: number }
|
||||
>Beast : Symbol(Beast, Decl(typeGuardIntersectionTypes.ts, 53, 38))
|
||||
>wings : Symbol(Beast.wings, Decl(typeGuardIntersectionTypes.ts, 56, 21))
|
||||
>legs : Symbol(Beast.legs, Decl(typeGuardIntersectionTypes.ts, 56, 38))
|
||||
|
||||
interface Legged { legs: number; }
|
||||
>Legged : Symbol(Legged, Decl(typeGuardIntersectionTypes.ts, 56, 54))
|
||||
>legs : Symbol(Legged.legs, Decl(typeGuardIntersectionTypes.ts, 57, 21))
|
||||
|
||||
interface Winged { wings: boolean; }
|
||||
>Winged : Symbol(Winged, Decl(typeGuardIntersectionTypes.ts, 57, 37))
|
||||
>wings : Symbol(Winged.wings, Decl(typeGuardIntersectionTypes.ts, 58, 21))
|
||||
|
||||
// Beast feature detection via user-defined type guards
|
||||
function hasLegs(x: Beast): x is Legged { return x && typeof x.legs === 'number'; }
|
||||
>hasLegs : Symbol(hasLegs, Decl(typeGuardIntersectionTypes.ts, 58, 39))
|
||||
>x : Symbol(x, Decl(typeGuardIntersectionTypes.ts, 61, 17))
|
||||
>Beast : Symbol(Beast, Decl(typeGuardIntersectionTypes.ts, 53, 38))
|
||||
>x : Symbol(x, Decl(typeGuardIntersectionTypes.ts, 61, 17))
|
||||
>Legged : Symbol(Legged, Decl(typeGuardIntersectionTypes.ts, 56, 54))
|
||||
>x : Symbol(x, Decl(typeGuardIntersectionTypes.ts, 61, 17))
|
||||
>x.legs : Symbol(Beast.legs, Decl(typeGuardIntersectionTypes.ts, 56, 38))
|
||||
>x : Symbol(x, Decl(typeGuardIntersectionTypes.ts, 61, 17))
|
||||
>legs : Symbol(Beast.legs, Decl(typeGuardIntersectionTypes.ts, 56, 38))
|
||||
|
||||
function hasWings(x: Beast): x is Winged { return x && !!x.wings; }
|
||||
>hasWings : Symbol(hasWings, Decl(typeGuardIntersectionTypes.ts, 61, 83))
|
||||
>x : Symbol(x, Decl(typeGuardIntersectionTypes.ts, 62, 18))
|
||||
>Beast : Symbol(Beast, Decl(typeGuardIntersectionTypes.ts, 53, 38))
|
||||
>x : Symbol(x, Decl(typeGuardIntersectionTypes.ts, 62, 18))
|
||||
>Winged : Symbol(Winged, Decl(typeGuardIntersectionTypes.ts, 57, 37))
|
||||
>x : Symbol(x, Decl(typeGuardIntersectionTypes.ts, 62, 18))
|
||||
>x.wings : Symbol(Beast.wings, Decl(typeGuardIntersectionTypes.ts, 56, 21))
|
||||
>x : Symbol(x, Decl(typeGuardIntersectionTypes.ts, 62, 18))
|
||||
>wings : Symbol(Beast.wings, Decl(typeGuardIntersectionTypes.ts, 56, 21))
|
||||
|
||||
// Function to identify a given beast by detecting its features
|
||||
function identifyBeast(beast: Beast) {
|
||||
>identifyBeast : Symbol(identifyBeast, Decl(typeGuardIntersectionTypes.ts, 62, 67))
|
||||
>beast : Symbol(beast, Decl(typeGuardIntersectionTypes.ts, 65, 23))
|
||||
>Beast : Symbol(Beast, Decl(typeGuardIntersectionTypes.ts, 53, 38))
|
||||
|
||||
// All beasts with legs
|
||||
if (hasLegs(beast)) {
|
||||
>hasLegs : Symbol(hasLegs, Decl(typeGuardIntersectionTypes.ts, 58, 39))
|
||||
>beast : Symbol(beast, Decl(typeGuardIntersectionTypes.ts, 65, 23))
|
||||
|
||||
// All winged beasts with legs
|
||||
if (hasWings(beast)) {
|
||||
>hasWings : Symbol(hasWings, Decl(typeGuardIntersectionTypes.ts, 61, 83))
|
||||
>beast : Symbol(beast, Decl(typeGuardIntersectionTypes.ts, 65, 23))
|
||||
|
||||
if (beast.legs === 4) { // ERROR TS2339: Property 'legs' does not exist on type 'Winged'.
|
||||
>beast.legs : Symbol(Legged.legs, Decl(typeGuardIntersectionTypes.ts, 57, 21))
|
||||
>beast : Symbol(beast, Decl(typeGuardIntersectionTypes.ts, 65, 23))
|
||||
>legs : Symbol(Legged.legs, Decl(typeGuardIntersectionTypes.ts, 57, 21))
|
||||
|
||||
log(`pegasus - 4 legs, wings`);
|
||||
>log : Symbol(log, Decl(typeGuardIntersectionTypes.ts, 49, 1))
|
||||
}
|
||||
else if (beast.legs === 2) { // ERROR TS2339...
|
||||
>beast.legs : Symbol(Legged.legs, Decl(typeGuardIntersectionTypes.ts, 57, 21))
|
||||
>beast : Symbol(beast, Decl(typeGuardIntersectionTypes.ts, 65, 23))
|
||||
>legs : Symbol(Legged.legs, Decl(typeGuardIntersectionTypes.ts, 57, 21))
|
||||
|
||||
log(`bird - 2 legs, wings`);
|
||||
>log : Symbol(log, Decl(typeGuardIntersectionTypes.ts, 49, 1))
|
||||
}
|
||||
else {
|
||||
log(`unknown - ${beast.legs} legs, wings`); // ERROR TS2339...
|
||||
>log : Symbol(log, Decl(typeGuardIntersectionTypes.ts, 49, 1))
|
||||
>beast.legs : Symbol(Legged.legs, Decl(typeGuardIntersectionTypes.ts, 57, 21))
|
||||
>beast : Symbol(beast, Decl(typeGuardIntersectionTypes.ts, 65, 23))
|
||||
>legs : Symbol(Legged.legs, Decl(typeGuardIntersectionTypes.ts, 57, 21))
|
||||
}
|
||||
}
|
||||
|
||||
// All non-winged beasts with legs
|
||||
else {
|
||||
log(`manbearpig - ${beast.legs} legs, no wings`);
|
||||
>log : Symbol(log, Decl(typeGuardIntersectionTypes.ts, 49, 1))
|
||||
>beast.legs : Symbol(Legged.legs, Decl(typeGuardIntersectionTypes.ts, 57, 21))
|
||||
>beast : Symbol(beast, Decl(typeGuardIntersectionTypes.ts, 65, 23))
|
||||
>legs : Symbol(Legged.legs, Decl(typeGuardIntersectionTypes.ts, 57, 21))
|
||||
}
|
||||
}
|
||||
|
||||
// All beasts without legs
|
||||
else {
|
||||
if (hasWings(beast)) {
|
||||
>hasWings : Symbol(hasWings, Decl(typeGuardIntersectionTypes.ts, 61, 83))
|
||||
>beast : Symbol(beast, Decl(typeGuardIntersectionTypes.ts, 65, 23))
|
||||
|
||||
log(`quetzalcoatl - no legs, wings`)
|
||||
>log : Symbol(log, Decl(typeGuardIntersectionTypes.ts, 49, 1))
|
||||
}
|
||||
else {
|
||||
log(`snake - no legs, no wings`)
|
||||
>log : Symbol(log, Decl(typeGuardIntersectionTypes.ts, 49, 1))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function beastFoo(beast: Object) {
|
||||
>beastFoo : Symbol(beastFoo, Decl(typeGuardIntersectionTypes.ts, 98, 1))
|
||||
>beast : Symbol(beast, Decl(typeGuardIntersectionTypes.ts, 100, 18))
|
||||
>Object : Symbol(Object, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
|
||||
if (hasWings(beast) && hasLegs(beast)) {
|
||||
>hasWings : Symbol(hasWings, Decl(typeGuardIntersectionTypes.ts, 61, 83))
|
||||
>beast : Symbol(beast, Decl(typeGuardIntersectionTypes.ts, 100, 18))
|
||||
>hasLegs : Symbol(hasLegs, Decl(typeGuardIntersectionTypes.ts, 58, 39))
|
||||
>beast : Symbol(beast, Decl(typeGuardIntersectionTypes.ts, 100, 18))
|
||||
|
||||
beast // beast is Legged
|
||||
>beast : Symbol(beast, Decl(typeGuardIntersectionTypes.ts, 100, 18))
|
||||
|
||||
// ideally, beast would be Winged && Legged here...
|
||||
}
|
||||
else {
|
||||
beast
|
||||
>beast : Symbol(beast, Decl(typeGuardIntersectionTypes.ts, 100, 18))
|
||||
}
|
||||
|
||||
if (hasLegs(beast) && hasWings(beast)) {
|
||||
>hasLegs : Symbol(hasLegs, Decl(typeGuardIntersectionTypes.ts, 58, 39))
|
||||
>beast : Symbol(beast, Decl(typeGuardIntersectionTypes.ts, 100, 18))
|
||||
>hasWings : Symbol(hasWings, Decl(typeGuardIntersectionTypes.ts, 61, 83))
|
||||
>beast : Symbol(beast, Decl(typeGuardIntersectionTypes.ts, 100, 18))
|
||||
|
||||
beast // beast is Winged
|
||||
>beast : Symbol(beast, Decl(typeGuardIntersectionTypes.ts, 100, 18))
|
||||
|
||||
// ideally, beast would be Legged && Winged here...
|
||||
}
|
||||
}
|
||||
310
tests/baselines/reference/typeGuardIntersectionTypes.types
Normal file
310
tests/baselines/reference/typeGuardIntersectionTypes.types
Normal file
@@ -0,0 +1,310 @@
|
||||
=== tests/cases/conformance/expressions/typeGuards/typeGuardIntersectionTypes.ts ===
|
||||
|
||||
interface X {
|
||||
>X : X
|
||||
|
||||
x: string;
|
||||
>x : string
|
||||
}
|
||||
|
||||
interface Y {
|
||||
>Y : Y
|
||||
|
||||
y: string;
|
||||
>y : string
|
||||
}
|
||||
|
||||
interface Z {
|
||||
>Z : Z
|
||||
|
||||
z: string;
|
||||
>z : string
|
||||
}
|
||||
|
||||
declare function isX(obj: any): obj is X;
|
||||
>isX : (obj: any) => obj is X
|
||||
>obj : any
|
||||
>obj : any
|
||||
>X : X
|
||||
|
||||
declare function isY(obj: any): obj is Y;
|
||||
>isY : (obj: any) => obj is Y
|
||||
>obj : any
|
||||
>obj : any
|
||||
>Y : Y
|
||||
|
||||
declare function isZ(obj: any): obj is Z;
|
||||
>isZ : (obj: any) => obj is Z
|
||||
>obj : any
|
||||
>obj : any
|
||||
>Z : Z
|
||||
|
||||
function f1(obj: Object) {
|
||||
>f1 : (obj: Object) => void
|
||||
>obj : Object
|
||||
>Object : Object
|
||||
|
||||
if (isX(obj) || isY(obj) || isZ(obj)) {
|
||||
>isX(obj) || isY(obj) || isZ(obj) : boolean
|
||||
>isX(obj) || isY(obj) : boolean
|
||||
>isX(obj) : boolean
|
||||
>isX : (obj: any) => obj is X
|
||||
>obj : Object
|
||||
>isY(obj) : boolean
|
||||
>isY : (obj: any) => obj is Y
|
||||
>obj : Object
|
||||
>isZ(obj) : boolean
|
||||
>isZ : (obj: any) => obj is Z
|
||||
>obj : Object
|
||||
|
||||
obj;
|
||||
>obj : X | Y | Z
|
||||
}
|
||||
if (isX(obj) && isY(obj) && isZ(obj)) {
|
||||
>isX(obj) && isY(obj) && isZ(obj) : boolean
|
||||
>isX(obj) && isY(obj) : boolean
|
||||
>isX(obj) : boolean
|
||||
>isX : (obj: any) => obj is X
|
||||
>obj : Object
|
||||
>isY(obj) : boolean
|
||||
>isY : (obj: any) => obj is Y
|
||||
>obj : X
|
||||
>isZ(obj) : boolean
|
||||
>isZ : (obj: any) => obj is Z
|
||||
>obj : X & Y
|
||||
|
||||
obj;
|
||||
>obj : X & Y & Z
|
||||
}
|
||||
}
|
||||
|
||||
// Repro from #8911
|
||||
|
||||
// two interfaces
|
||||
interface A {
|
||||
>A : A
|
||||
|
||||
a: string;
|
||||
>a : string
|
||||
}
|
||||
|
||||
interface B {
|
||||
>B : B
|
||||
|
||||
b: string;
|
||||
>b : string
|
||||
}
|
||||
|
||||
// a type guard for B
|
||||
function isB(toTest: any): toTest is B {
|
||||
>isB : (toTest: any) => toTest is B
|
||||
>toTest : any
|
||||
>toTest : any
|
||||
>B : B
|
||||
|
||||
return toTest && toTest.b;
|
||||
>toTest && toTest.b : any
|
||||
>toTest : any
|
||||
>toTest.b : any
|
||||
>toTest : any
|
||||
>b : any
|
||||
}
|
||||
|
||||
// a function that turns an A into an A & B
|
||||
function union(a: A): A & B | null {
|
||||
>union : (a: A) => (A & B) | null
|
||||
>a : A
|
||||
>A : A
|
||||
>A : A
|
||||
>B : B
|
||||
>null : null
|
||||
|
||||
if (isB(a)) {
|
||||
>isB(a) : boolean
|
||||
>isB : (toTest: any) => toTest is B
|
||||
>a : A
|
||||
|
||||
return a;
|
||||
>a : A & B
|
||||
|
||||
} else {
|
||||
return null;
|
||||
>null : null
|
||||
}
|
||||
}
|
||||
|
||||
// Repro from #9011
|
||||
|
||||
declare function log(s: string): void;
|
||||
>log : (s: string) => void
|
||||
>s : string
|
||||
|
||||
// Supported beast features
|
||||
interface Beast { wings?: boolean; legs?: number }
|
||||
>Beast : Beast
|
||||
>wings : boolean | undefined
|
||||
>legs : number | undefined
|
||||
|
||||
interface Legged { legs: number; }
|
||||
>Legged : Legged
|
||||
>legs : number
|
||||
|
||||
interface Winged { wings: boolean; }
|
||||
>Winged : Winged
|
||||
>wings : boolean
|
||||
|
||||
// Beast feature detection via user-defined type guards
|
||||
function hasLegs(x: Beast): x is Legged { return x && typeof x.legs === 'number'; }
|
||||
>hasLegs : (x: Beast) => x is Legged
|
||||
>x : Beast
|
||||
>Beast : Beast
|
||||
>x : any
|
||||
>Legged : Legged
|
||||
>x && typeof x.legs === 'number' : boolean
|
||||
>x : Beast
|
||||
>typeof x.legs === 'number' : boolean
|
||||
>typeof x.legs : string
|
||||
>x.legs : number | undefined
|
||||
>x : Beast
|
||||
>legs : number | undefined
|
||||
>'number' : string
|
||||
|
||||
function hasWings(x: Beast): x is Winged { return x && !!x.wings; }
|
||||
>hasWings : (x: Beast) => x is Winged
|
||||
>x : Beast
|
||||
>Beast : Beast
|
||||
>x : any
|
||||
>Winged : Winged
|
||||
>x && !!x.wings : boolean
|
||||
>x : Beast
|
||||
>!!x.wings : boolean
|
||||
>!x.wings : boolean
|
||||
>x.wings : boolean | undefined
|
||||
>x : Beast
|
||||
>wings : boolean | undefined
|
||||
|
||||
// Function to identify a given beast by detecting its features
|
||||
function identifyBeast(beast: Beast) {
|
||||
>identifyBeast : (beast: Beast) => void
|
||||
>beast : Beast
|
||||
>Beast : Beast
|
||||
|
||||
// All beasts with legs
|
||||
if (hasLegs(beast)) {
|
||||
>hasLegs(beast) : boolean
|
||||
>hasLegs : (x: Beast) => x is Legged
|
||||
>beast : Beast
|
||||
|
||||
// All winged beasts with legs
|
||||
if (hasWings(beast)) {
|
||||
>hasWings(beast) : boolean
|
||||
>hasWings : (x: Beast) => x is Winged
|
||||
>beast : Legged
|
||||
|
||||
if (beast.legs === 4) { // ERROR TS2339: Property 'legs' does not exist on type 'Winged'.
|
||||
>beast.legs === 4 : boolean
|
||||
>beast.legs : number
|
||||
>beast : Legged & Winged
|
||||
>legs : number
|
||||
>4 : number
|
||||
|
||||
log(`pegasus - 4 legs, wings`);
|
||||
>log(`pegasus - 4 legs, wings`) : void
|
||||
>log : (s: string) => void
|
||||
>`pegasus - 4 legs, wings` : string
|
||||
}
|
||||
else if (beast.legs === 2) { // ERROR TS2339...
|
||||
>beast.legs === 2 : boolean
|
||||
>beast.legs : number
|
||||
>beast : Legged & Winged
|
||||
>legs : number
|
||||
>2 : number
|
||||
|
||||
log(`bird - 2 legs, wings`);
|
||||
>log(`bird - 2 legs, wings`) : void
|
||||
>log : (s: string) => void
|
||||
>`bird - 2 legs, wings` : string
|
||||
}
|
||||
else {
|
||||
log(`unknown - ${beast.legs} legs, wings`); // ERROR TS2339...
|
||||
>log(`unknown - ${beast.legs} legs, wings`) : void
|
||||
>log : (s: string) => void
|
||||
>`unknown - ${beast.legs} legs, wings` : string
|
||||
>beast.legs : number
|
||||
>beast : Legged & Winged
|
||||
>legs : number
|
||||
}
|
||||
}
|
||||
|
||||
// All non-winged beasts with legs
|
||||
else {
|
||||
log(`manbearpig - ${beast.legs} legs, no wings`);
|
||||
>log(`manbearpig - ${beast.legs} legs, no wings`) : void
|
||||
>log : (s: string) => void
|
||||
>`manbearpig - ${beast.legs} legs, no wings` : string
|
||||
>beast.legs : number
|
||||
>beast : Legged
|
||||
>legs : number
|
||||
}
|
||||
}
|
||||
|
||||
// All beasts without legs
|
||||
else {
|
||||
if (hasWings(beast)) {
|
||||
>hasWings(beast) : boolean
|
||||
>hasWings : (x: Beast) => x is Winged
|
||||
>beast : Beast
|
||||
|
||||
log(`quetzalcoatl - no legs, wings`)
|
||||
>log(`quetzalcoatl - no legs, wings`) : void
|
||||
>log : (s: string) => void
|
||||
>`quetzalcoatl - no legs, wings` : string
|
||||
}
|
||||
else {
|
||||
log(`snake - no legs, no wings`)
|
||||
>log(`snake - no legs, no wings`) : void
|
||||
>log : (s: string) => void
|
||||
>`snake - no legs, no wings` : string
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function beastFoo(beast: Object) {
|
||||
>beastFoo : (beast: Object) => void
|
||||
>beast : Object
|
||||
>Object : Object
|
||||
|
||||
if (hasWings(beast) && hasLegs(beast)) {
|
||||
>hasWings(beast) && hasLegs(beast) : boolean
|
||||
>hasWings(beast) : boolean
|
||||
>hasWings : (x: Beast) => x is Winged
|
||||
>beast : Object
|
||||
>hasLegs(beast) : boolean
|
||||
>hasLegs : (x: Beast) => x is Legged
|
||||
>beast : Winged
|
||||
|
||||
beast // beast is Legged
|
||||
>beast : Winged & Legged
|
||||
|
||||
// ideally, beast would be Winged && Legged here...
|
||||
}
|
||||
else {
|
||||
beast
|
||||
>beast : Object
|
||||
}
|
||||
|
||||
if (hasLegs(beast) && hasWings(beast)) {
|
||||
>hasLegs(beast) && hasWings(beast) : boolean
|
||||
>hasLegs(beast) : boolean
|
||||
>hasLegs : (x: Beast) => x is Legged
|
||||
>beast : Object
|
||||
>hasWings(beast) : boolean
|
||||
>hasWings : (x: Beast) => x is Winged
|
||||
>beast : Legged
|
||||
|
||||
beast // beast is Winged
|
||||
>beast : Legged & Winged
|
||||
|
||||
// ideally, beast would be Legged && Winged here...
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
// @strictNullChecks: true
|
||||
|
||||
interface X {
|
||||
x: string;
|
||||
}
|
||||
|
||||
interface Y {
|
||||
y: string;
|
||||
}
|
||||
|
||||
interface Z {
|
||||
z: string;
|
||||
}
|
||||
|
||||
declare function isX(obj: any): obj is X;
|
||||
declare function isY(obj: any): obj is Y;
|
||||
declare function isZ(obj: any): obj is Z;
|
||||
|
||||
function f1(obj: Object) {
|
||||
if (isX(obj) || isY(obj) || isZ(obj)) {
|
||||
obj;
|
||||
}
|
||||
if (isX(obj) && isY(obj) && isZ(obj)) {
|
||||
obj;
|
||||
}
|
||||
}
|
||||
|
||||
// Repro from #8911
|
||||
|
||||
// two interfaces
|
||||
interface A {
|
||||
a: string;
|
||||
}
|
||||
|
||||
interface B {
|
||||
b: string;
|
||||
}
|
||||
|
||||
// a type guard for B
|
||||
function isB(toTest: any): toTest is B {
|
||||
return toTest && toTest.b;
|
||||
}
|
||||
|
||||
// a function that turns an A into an A & B
|
||||
function union(a: A): A & B | null {
|
||||
if (isB(a)) {
|
||||
return a;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Repro from #9011
|
||||
|
||||
declare function log(s: string): void;
|
||||
|
||||
// Supported beast features
|
||||
interface Beast { wings?: boolean; legs?: number }
|
||||
interface Legged { legs: number; }
|
||||
interface Winged { wings: boolean; }
|
||||
|
||||
// Beast feature detection via user-defined type guards
|
||||
function hasLegs(x: Beast): x is Legged { return x && typeof x.legs === 'number'; }
|
||||
function hasWings(x: Beast): x is Winged { return x && !!x.wings; }
|
||||
|
||||
// Function to identify a given beast by detecting its features
|
||||
function identifyBeast(beast: Beast) {
|
||||
|
||||
// All beasts with legs
|
||||
if (hasLegs(beast)) {
|
||||
|
||||
// All winged beasts with legs
|
||||
if (hasWings(beast)) {
|
||||
if (beast.legs === 4) { // ERROR TS2339: Property 'legs' does not exist on type 'Winged'.
|
||||
log(`pegasus - 4 legs, wings`);
|
||||
}
|
||||
else if (beast.legs === 2) { // ERROR TS2339...
|
||||
log(`bird - 2 legs, wings`);
|
||||
}
|
||||
else {
|
||||
log(`unknown - ${beast.legs} legs, wings`); // ERROR TS2339...
|
||||
}
|
||||
}
|
||||
|
||||
// All non-winged beasts with legs
|
||||
else {
|
||||
log(`manbearpig - ${beast.legs} legs, no wings`);
|
||||
}
|
||||
}
|
||||
|
||||
// All beasts without legs
|
||||
else {
|
||||
if (hasWings(beast)) {
|
||||
log(`quetzalcoatl - no legs, wings`)
|
||||
}
|
||||
else {
|
||||
log(`snake - no legs, no wings`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function beastFoo(beast: Object) {
|
||||
if (hasWings(beast) && hasLegs(beast)) {
|
||||
beast // beast is Legged
|
||||
// ideally, beast would be Winged && Legged here...
|
||||
}
|
||||
else {
|
||||
beast
|
||||
}
|
||||
|
||||
if (hasLegs(beast) && hasWings(beast)) {
|
||||
beast // beast is Winged
|
||||
// ideally, beast would be Legged && Winged here...
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user