mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-13 16:34:39 -06:00
Add initial support for 'in' typeguarding
This commit is contained in:
parent
7bb5fc22c2
commit
9c3c2adfb0
@ -749,6 +749,10 @@ namespace ts {
|
||||
return expr1.kind === SyntaxKind.TypeOfExpression && isNarrowableOperand((<TypeOfExpression>expr1).expression) && expr2.kind === SyntaxKind.StringLiteral;
|
||||
}
|
||||
|
||||
function isNarrowableInOperands(left: Expression, right: Expression) {
|
||||
return left.kind === SyntaxKind.StringLiteral && isNarrowingExpression(right);
|
||||
}
|
||||
|
||||
function isNarrowingBinaryExpression(expr: BinaryExpression) {
|
||||
switch (expr.operatorToken.kind) {
|
||||
case SyntaxKind.EqualsToken:
|
||||
@ -761,6 +765,8 @@ namespace ts {
|
||||
isNarrowingTypeofOperands(expr.right, expr.left) || isNarrowingTypeofOperands(expr.left, expr.right);
|
||||
case SyntaxKind.InstanceOfKeyword:
|
||||
return isNarrowableOperand(expr.left);
|
||||
case SyntaxKind.InKeyword:
|
||||
return isNarrowableInOperands(expr.left, expr.right);
|
||||
case SyntaxKind.CommaToken:
|
||||
return isNarrowingExpression(expr.right);
|
||||
}
|
||||
|
||||
@ -12722,6 +12722,14 @@ namespace ts {
|
||||
return type;
|
||||
}
|
||||
|
||||
function narrowByInKeyword(type: Type, literal: LiteralExpression, assumeTrue: boolean) {
|
||||
if ((type.flags & (TypeFlags.Union | TypeFlags.Object)) || (type.flags & TypeFlags.TypeParameter && (type as TypeParameter).isThisType)) {
|
||||
const propName = literal.text;
|
||||
return filterType(type, t => !!getPropertyOfType(t, propName) === assumeTrue);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
function narrowTypeByBinaryExpression(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type {
|
||||
switch (expr.operatorToken.kind) {
|
||||
case SyntaxKind.EqualsToken:
|
||||
@ -12757,6 +12765,12 @@ namespace ts {
|
||||
break;
|
||||
case SyntaxKind.InstanceOfKeyword:
|
||||
return narrowTypeByInstanceof(type, expr, assumeTrue);
|
||||
case SyntaxKind.InKeyword:
|
||||
const target = getReferenceCandidate(expr.right);
|
||||
if (expr.left.kind === SyntaxKind.StringLiteral && isMatchingReference(reference, target)) {
|
||||
return narrowByInKeyword(type, <LiteralExpression>expr.left, assumeTrue);
|
||||
}
|
||||
break;
|
||||
case SyntaxKind.CommaToken:
|
||||
return narrowType(type, expr.right, assumeTrue);
|
||||
}
|
||||
|
||||
154
tests/baselines/reference/inKeywordTypeguard.errors.txt
Normal file
154
tests/baselines/reference/inKeywordTypeguard.errors.txt
Normal file
@ -0,0 +1,154 @@
|
||||
tests/cases/compiler/inKeywordTypeguard.ts(6,11): error TS2339: Property 'b' does not exist on type 'A'.
|
||||
tests/cases/compiler/inKeywordTypeguard.ts(8,11): error TS2339: Property 'a' does not exist on type 'B'.
|
||||
tests/cases/compiler/inKeywordTypeguard.ts(14,11): error TS2339: Property 'b' does not exist on type 'A'.
|
||||
tests/cases/compiler/inKeywordTypeguard.ts(16,11): error TS2339: Property 'a' does not exist on type 'B'.
|
||||
tests/cases/compiler/inKeywordTypeguard.ts(42,11): error TS2339: Property 'b' does not exist on type 'AWithMethod'.
|
||||
tests/cases/compiler/inKeywordTypeguard.ts(49,11): error TS2339: Property 'a' does not exist on type 'never'.
|
||||
tests/cases/compiler/inKeywordTypeguard.ts(50,11): error TS2339: Property 'b' does not exist on type 'never'.
|
||||
tests/cases/compiler/inKeywordTypeguard.ts(52,11): error TS2339: Property 'a' does not exist on type 'AWithMethod | BWithMethod'.
|
||||
Property 'a' does not exist on type 'BWithMethod'.
|
||||
tests/cases/compiler/inKeywordTypeguard.ts(53,11): error TS2339: Property 'b' does not exist on type 'AWithMethod | BWithMethod'.
|
||||
Property 'b' does not exist on type 'AWithMethod'.
|
||||
tests/cases/compiler/inKeywordTypeguard.ts(62,11): error TS2339: Property 'b' does not exist on type 'A | C | D'.
|
||||
Property 'b' does not exist on type 'A'.
|
||||
tests/cases/compiler/inKeywordTypeguard.ts(64,11): error TS2339: Property 'a' does not exist on type 'B'.
|
||||
tests/cases/compiler/inKeywordTypeguard.ts(72,32): error TS2339: Property 'b' does not exist on type 'A'.
|
||||
tests/cases/compiler/inKeywordTypeguard.ts(74,32): error TS2339: Property 'a' does not exist on type 'B'.
|
||||
tests/cases/compiler/inKeywordTypeguard.ts(82,39): error TS2339: Property 'b' does not exist on type 'A'.
|
||||
tests/cases/compiler/inKeywordTypeguard.ts(84,39): error TS2339: Property 'a' does not exist on type 'B'.
|
||||
tests/cases/compiler/inKeywordTypeguard.ts(94,26): error TS2339: Property 'a' does not exist on type 'never'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/inKeywordTypeguard.ts (16 errors) ====
|
||||
class A { a: string; }
|
||||
class B { b: string; }
|
||||
|
||||
function negativeClassesTest(x: A | B) {
|
||||
if ("a" in x) {
|
||||
x.b = "1";
|
||||
~
|
||||
!!! error TS2339: Property 'b' does not exist on type 'A'.
|
||||
} else {
|
||||
x.a = "1";
|
||||
~
|
||||
!!! error TS2339: Property 'a' does not exist on type 'B'.
|
||||
}
|
||||
}
|
||||
|
||||
function positiveClassesTest(x: A | B) {
|
||||
if ("a" in x) {
|
||||
x.b = "1";
|
||||
~
|
||||
!!! error TS2339: Property 'b' does not exist on type 'A'.
|
||||
} else {
|
||||
x.a = "1";
|
||||
~
|
||||
!!! error TS2339: Property 'a' does not exist on type 'B'.
|
||||
}
|
||||
}
|
||||
|
||||
class AOpt { a?: string }
|
||||
class BOpn { b?: string }
|
||||
|
||||
function positiveTestClassesWithOptionalProperties(x: AOpt | BOpn) {
|
||||
if ("a" in x) {
|
||||
x.a = "1";
|
||||
} else {
|
||||
x.b = "1";
|
||||
}
|
||||
}
|
||||
|
||||
class AWithMethod {
|
||||
a(): string { return "" }
|
||||
}
|
||||
|
||||
class BWithMethod {
|
||||
b(): string { return "" }
|
||||
}
|
||||
|
||||
function negativeTestClassesWithMembers(x: AWithMethod | BWithMethod) {
|
||||
if ("a" in x) {
|
||||
x.a();
|
||||
x.b();
|
||||
~
|
||||
!!! error TS2339: Property 'b' does not exist on type 'AWithMethod'.
|
||||
} else {
|
||||
}
|
||||
}
|
||||
|
||||
function negativeTestClassesWithMemberMissingInBothClasses(x: AWithMethod | BWithMethod) {
|
||||
if ("c" in x) {
|
||||
x.a();
|
||||
~
|
||||
!!! error TS2339: Property 'a' does not exist on type 'never'.
|
||||
x.b();
|
||||
~
|
||||
!!! error TS2339: Property 'b' does not exist on type 'never'.
|
||||
} else {
|
||||
x.a();
|
||||
~
|
||||
!!! error TS2339: Property 'a' does not exist on type 'AWithMethod | BWithMethod'.
|
||||
!!! error TS2339: Property 'a' does not exist on type 'BWithMethod'.
|
||||
x.b();
|
||||
~
|
||||
!!! error TS2339: Property 'b' does not exist on type 'AWithMethod | BWithMethod'.
|
||||
!!! error TS2339: Property 'b' does not exist on type 'AWithMethod'.
|
||||
}
|
||||
}
|
||||
|
||||
class C { a: string }
|
||||
class D { a: string }
|
||||
|
||||
function negativeMultipleClassesTest(x: A | B | C | D) {
|
||||
if ("a" in x) {
|
||||
x.b = "1";
|
||||
~
|
||||
!!! error TS2339: Property 'b' does not exist on type 'A | C | D'.
|
||||
!!! error TS2339: Property 'b' does not exist on type 'A'.
|
||||
} else {
|
||||
x.a = "1";
|
||||
~
|
||||
!!! error TS2339: Property 'a' does not exist on type 'B'.
|
||||
}
|
||||
}
|
||||
|
||||
class ClassWithProp { prop: A | B }
|
||||
|
||||
function negativePropTest(x: ClassWithProp) {
|
||||
if ("a" in x.prop) {
|
||||
let y: string = x.prop.b;
|
||||
~
|
||||
!!! error TS2339: Property 'b' does not exist on type 'A'.
|
||||
} else {
|
||||
let z: string = x.prop.a;
|
||||
~
|
||||
!!! error TS2339: Property 'a' does not exist on type 'B'.
|
||||
}
|
||||
}
|
||||
|
||||
class NegativeClassTest {
|
||||
protected prop: A | B;
|
||||
inThis() {
|
||||
if ('a' in this.prop) {
|
||||
let z: number = this.prop.b;
|
||||
~
|
||||
!!! error TS2339: Property 'b' does not exist on type 'A'.
|
||||
} else {
|
||||
let y: string = this.prop.a;
|
||||
~
|
||||
!!! error TS2339: Property 'a' does not exist on type 'B'.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class UnreachableCodeDetection {
|
||||
a: string;
|
||||
inThis() {
|
||||
if ('a' in this) {
|
||||
} else {
|
||||
let y = this.a;
|
||||
~
|
||||
!!! error TS2339: Property 'a' does not exist on type 'never'.
|
||||
}
|
||||
}
|
||||
}
|
||||
230
tests/baselines/reference/inKeywordTypeguard.js
Normal file
230
tests/baselines/reference/inKeywordTypeguard.js
Normal file
@ -0,0 +1,230 @@
|
||||
//// [inKeywordTypeguard.ts]
|
||||
class A { a: string; }
|
||||
class B { b: string; }
|
||||
|
||||
function negativeClassesTest(x: A | B) {
|
||||
if ("a" in x) {
|
||||
x.b = "1";
|
||||
} else {
|
||||
x.a = "1";
|
||||
}
|
||||
}
|
||||
|
||||
function positiveClassesTest(x: A | B) {
|
||||
if ("a" in x) {
|
||||
x.b = "1";
|
||||
} else {
|
||||
x.a = "1";
|
||||
}
|
||||
}
|
||||
|
||||
class AOpt { a?: string }
|
||||
class BOpn { b?: string }
|
||||
|
||||
function positiveTestClassesWithOptionalProperties(x: AOpt | BOpn) {
|
||||
if ("a" in x) {
|
||||
x.a = "1";
|
||||
} else {
|
||||
x.b = "1";
|
||||
}
|
||||
}
|
||||
|
||||
class AWithMethod {
|
||||
a(): string { return "" }
|
||||
}
|
||||
|
||||
class BWithMethod {
|
||||
b(): string { return "" }
|
||||
}
|
||||
|
||||
function negativeTestClassesWithMembers(x: AWithMethod | BWithMethod) {
|
||||
if ("a" in x) {
|
||||
x.a();
|
||||
x.b();
|
||||
} else {
|
||||
}
|
||||
}
|
||||
|
||||
function negativeTestClassesWithMemberMissingInBothClasses(x: AWithMethod | BWithMethod) {
|
||||
if ("c" in x) {
|
||||
x.a();
|
||||
x.b();
|
||||
} else {
|
||||
x.a();
|
||||
x.b();
|
||||
}
|
||||
}
|
||||
|
||||
class C { a: string }
|
||||
class D { a: string }
|
||||
|
||||
function negativeMultipleClassesTest(x: A | B | C | D) {
|
||||
if ("a" in x) {
|
||||
x.b = "1";
|
||||
} else {
|
||||
x.a = "1";
|
||||
}
|
||||
}
|
||||
|
||||
class ClassWithProp { prop: A | B }
|
||||
|
||||
function negativePropTest(x: ClassWithProp) {
|
||||
if ("a" in x.prop) {
|
||||
let y: string = x.prop.b;
|
||||
} else {
|
||||
let z: string = x.prop.a;
|
||||
}
|
||||
}
|
||||
|
||||
class NegativeClassTest {
|
||||
protected prop: A | B;
|
||||
inThis() {
|
||||
if ('a' in this.prop) {
|
||||
let z: number = this.prop.b;
|
||||
} else {
|
||||
let y: string = this.prop.a;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class UnreachableCodeDetection {
|
||||
a: string;
|
||||
inThis() {
|
||||
if ('a' in this) {
|
||||
} else {
|
||||
let y = this.a;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//// [inKeywordTypeguard.js]
|
||||
var A = (function () {
|
||||
function A() {
|
||||
}
|
||||
return A;
|
||||
}());
|
||||
var B = (function () {
|
||||
function B() {
|
||||
}
|
||||
return B;
|
||||
}());
|
||||
function negativeClassesTest(x) {
|
||||
if ("a" in x) {
|
||||
x.b = "1";
|
||||
}
|
||||
else {
|
||||
x.a = "1";
|
||||
}
|
||||
}
|
||||
function positiveClassesTest(x) {
|
||||
if ("a" in x) {
|
||||
x.b = "1";
|
||||
}
|
||||
else {
|
||||
x.a = "1";
|
||||
}
|
||||
}
|
||||
var AOpt = (function () {
|
||||
function AOpt() {
|
||||
}
|
||||
return AOpt;
|
||||
}());
|
||||
var BOpn = (function () {
|
||||
function BOpn() {
|
||||
}
|
||||
return BOpn;
|
||||
}());
|
||||
function positiveTestClassesWithOptionalProperties(x) {
|
||||
if ("a" in x) {
|
||||
x.a = "1";
|
||||
}
|
||||
else {
|
||||
x.b = "1";
|
||||
}
|
||||
}
|
||||
var AWithMethod = (function () {
|
||||
function AWithMethod() {
|
||||
}
|
||||
AWithMethod.prototype.a = function () { return ""; };
|
||||
return AWithMethod;
|
||||
}());
|
||||
var BWithMethod = (function () {
|
||||
function BWithMethod() {
|
||||
}
|
||||
BWithMethod.prototype.b = function () { return ""; };
|
||||
return BWithMethod;
|
||||
}());
|
||||
function negativeTestClassesWithMembers(x) {
|
||||
if ("a" in x) {
|
||||
x.a();
|
||||
x.b();
|
||||
}
|
||||
else {
|
||||
}
|
||||
}
|
||||
function negativeTestClassesWithMemberMissingInBothClasses(x) {
|
||||
if ("c" in x) {
|
||||
x.a();
|
||||
x.b();
|
||||
}
|
||||
else {
|
||||
x.a();
|
||||
x.b();
|
||||
}
|
||||
}
|
||||
var C = (function () {
|
||||
function C() {
|
||||
}
|
||||
return C;
|
||||
}());
|
||||
var D = (function () {
|
||||
function D() {
|
||||
}
|
||||
return D;
|
||||
}());
|
||||
function negativeMultipleClassesTest(x) {
|
||||
if ("a" in x) {
|
||||
x.b = "1";
|
||||
}
|
||||
else {
|
||||
x.a = "1";
|
||||
}
|
||||
}
|
||||
var ClassWithProp = (function () {
|
||||
function ClassWithProp() {
|
||||
}
|
||||
return ClassWithProp;
|
||||
}());
|
||||
function negativePropTest(x) {
|
||||
if ("a" in x.prop) {
|
||||
var y = x.prop.b;
|
||||
}
|
||||
else {
|
||||
var z = x.prop.a;
|
||||
}
|
||||
}
|
||||
var NegativeClassTest = (function () {
|
||||
function NegativeClassTest() {
|
||||
}
|
||||
NegativeClassTest.prototype.inThis = function () {
|
||||
if ('a' in this.prop) {
|
||||
var z = this.prop.b;
|
||||
}
|
||||
else {
|
||||
var y = this.prop.a;
|
||||
}
|
||||
};
|
||||
return NegativeClassTest;
|
||||
}());
|
||||
var UnreachableCodeDetection = (function () {
|
||||
function UnreachableCodeDetection() {
|
||||
}
|
||||
UnreachableCodeDetection.prototype.inThis = function () {
|
||||
if ('a' in this) {
|
||||
}
|
||||
else {
|
||||
var y = this.a;
|
||||
}
|
||||
};
|
||||
return UnreachableCodeDetection;
|
||||
}());
|
||||
184
tests/baselines/reference/typeGuardOfFromPropNameInUnionType.js
Normal file
184
tests/baselines/reference/typeGuardOfFromPropNameInUnionType.js
Normal file
@ -0,0 +1,184 @@
|
||||
//// [typeGuardOfFromPropNameInUnionType.ts]
|
||||
class A { a: string; }
|
||||
class B { b: number; }
|
||||
class C { b: Object; }
|
||||
class D { a: Date; }
|
||||
class ClassWithProp { prop: A | B }
|
||||
class NestedClassWithProp { outer: ClassWithProp }
|
||||
|
||||
function namedClasses(x: A | B) {
|
||||
if ("a" in x) {
|
||||
x.a = "1";
|
||||
} else {
|
||||
x.b = 1;
|
||||
}
|
||||
}
|
||||
|
||||
function multipleClasses(x: A | B | C | D) {
|
||||
if ("a" in x) {
|
||||
let y: string | Date = x.a;
|
||||
} else {
|
||||
let z: number | Object = x.b;
|
||||
}
|
||||
}
|
||||
|
||||
function anonymousClasses(x: { a: string; } | { b: number; }) {
|
||||
if ("a" in x) {
|
||||
let y: string = x.a;
|
||||
} else {
|
||||
let z: number = x.b;
|
||||
}
|
||||
}
|
||||
function inParenthesizedExpression(x: A | B) {
|
||||
if ("a" in (x)) {
|
||||
let y: string = x.a;
|
||||
} else {
|
||||
let z: number = x.b;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function inProperty(x: ClassWithProp) {
|
||||
if ("a" in x.prop) {
|
||||
let y: string = x.prop.a;
|
||||
} else {
|
||||
let z: number = x.prop.b;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function innestedProperty(x: NestedClassWithProp) {
|
||||
if ("a" in x.outer.prop) {
|
||||
let y: string = x.outer.prop.a;
|
||||
} else {
|
||||
let z: number = x.outer.prop.b;
|
||||
}
|
||||
}
|
||||
|
||||
class InMemberOfClass {
|
||||
protected prop: A | B;
|
||||
inThis() {
|
||||
if ('a' in this.prop) {
|
||||
let y: string = this.prop.a;
|
||||
} else {
|
||||
let z: number = this.prop.b;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//added for completeness
|
||||
class SelfAssert {
|
||||
a: string;
|
||||
inThis() {
|
||||
if ('a' in this) {
|
||||
let y: string = this.a;
|
||||
} else {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//// [typeGuardOfFromPropNameInUnionType.js]
|
||||
var A = (function () {
|
||||
function A() {
|
||||
}
|
||||
return A;
|
||||
}());
|
||||
var B = (function () {
|
||||
function B() {
|
||||
}
|
||||
return B;
|
||||
}());
|
||||
var C = (function () {
|
||||
function C() {
|
||||
}
|
||||
return C;
|
||||
}());
|
||||
var D = (function () {
|
||||
function D() {
|
||||
}
|
||||
return D;
|
||||
}());
|
||||
var ClassWithProp = (function () {
|
||||
function ClassWithProp() {
|
||||
}
|
||||
return ClassWithProp;
|
||||
}());
|
||||
var NestedClassWithProp = (function () {
|
||||
function NestedClassWithProp() {
|
||||
}
|
||||
return NestedClassWithProp;
|
||||
}());
|
||||
function namedClasses(x) {
|
||||
if ("a" in x) {
|
||||
x.a = "1";
|
||||
}
|
||||
else {
|
||||
x.b = 1;
|
||||
}
|
||||
}
|
||||
function multipleClasses(x) {
|
||||
if ("a" in x) {
|
||||
var y = x.a;
|
||||
}
|
||||
else {
|
||||
var z = x.b;
|
||||
}
|
||||
}
|
||||
function anonymousClasses(x) {
|
||||
if ("a" in x) {
|
||||
var y = x.a;
|
||||
}
|
||||
else {
|
||||
var z = x.b;
|
||||
}
|
||||
}
|
||||
function inParenthesizedExpression(x) {
|
||||
if ("a" in (x)) {
|
||||
var y = x.a;
|
||||
}
|
||||
else {
|
||||
var z = x.b;
|
||||
}
|
||||
}
|
||||
function inProperty(x) {
|
||||
if ("a" in x.prop) {
|
||||
var y = x.prop.a;
|
||||
}
|
||||
else {
|
||||
var z = x.prop.b;
|
||||
}
|
||||
}
|
||||
function innestedProperty(x) {
|
||||
if ("a" in x.outer.prop) {
|
||||
var y = x.outer.prop.a;
|
||||
}
|
||||
else {
|
||||
var z = x.outer.prop.b;
|
||||
}
|
||||
}
|
||||
var InMemberOfClass = (function () {
|
||||
function InMemberOfClass() {
|
||||
}
|
||||
InMemberOfClass.prototype.inThis = function () {
|
||||
if ('a' in this.prop) {
|
||||
var y = this.prop.a;
|
||||
}
|
||||
else {
|
||||
var z = this.prop.b;
|
||||
}
|
||||
};
|
||||
return InMemberOfClass;
|
||||
}());
|
||||
//added for completeness
|
||||
var SelfAssert = (function () {
|
||||
function SelfAssert() {
|
||||
}
|
||||
SelfAssert.prototype.inThis = function () {
|
||||
if ('a' in this) {
|
||||
var y = this.a;
|
||||
}
|
||||
else {
|
||||
}
|
||||
};
|
||||
return SelfAssert;
|
||||
}());
|
||||
@ -0,0 +1,252 @@
|
||||
=== tests/cases/conformance/expressions/typeGuards/typeGuardOfFromPropNameInUnionType.ts ===
|
||||
class A { a: string; }
|
||||
>A : Symbol(A, Decl(typeGuardOfFromPropNameInUnionType.ts, 0, 0))
|
||||
>a : Symbol(A.a, Decl(typeGuardOfFromPropNameInUnionType.ts, 0, 9))
|
||||
|
||||
class B { b: number; }
|
||||
>B : Symbol(B, Decl(typeGuardOfFromPropNameInUnionType.ts, 0, 22))
|
||||
>b : Symbol(B.b, Decl(typeGuardOfFromPropNameInUnionType.ts, 1, 9))
|
||||
|
||||
class C { b: Object; }
|
||||
>C : Symbol(C, Decl(typeGuardOfFromPropNameInUnionType.ts, 1, 22))
|
||||
>b : Symbol(C.b, Decl(typeGuardOfFromPropNameInUnionType.ts, 2, 9))
|
||||
>Object : Symbol(Object, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
|
||||
class D { a: Date; }
|
||||
>D : Symbol(D, Decl(typeGuardOfFromPropNameInUnionType.ts, 2, 22))
|
||||
>a : Symbol(D.a, Decl(typeGuardOfFromPropNameInUnionType.ts, 3, 9))
|
||||
>Date : Symbol(Date, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
|
||||
class ClassWithProp { prop: A | B }
|
||||
>ClassWithProp : Symbol(ClassWithProp, Decl(typeGuardOfFromPropNameInUnionType.ts, 3, 20))
|
||||
>prop : Symbol(ClassWithProp.prop, Decl(typeGuardOfFromPropNameInUnionType.ts, 4, 21))
|
||||
>A : Symbol(A, Decl(typeGuardOfFromPropNameInUnionType.ts, 0, 0))
|
||||
>B : Symbol(B, Decl(typeGuardOfFromPropNameInUnionType.ts, 0, 22))
|
||||
|
||||
class NestedClassWithProp { outer: ClassWithProp }
|
||||
>NestedClassWithProp : Symbol(NestedClassWithProp, Decl(typeGuardOfFromPropNameInUnionType.ts, 4, 35))
|
||||
>outer : Symbol(NestedClassWithProp.outer, Decl(typeGuardOfFromPropNameInUnionType.ts, 5, 27))
|
||||
>ClassWithProp : Symbol(ClassWithProp, Decl(typeGuardOfFromPropNameInUnionType.ts, 3, 20))
|
||||
|
||||
function namedClasses(x: A | B) {
|
||||
>namedClasses : Symbol(namedClasses, Decl(typeGuardOfFromPropNameInUnionType.ts, 5, 50))
|
||||
>x : Symbol(x, Decl(typeGuardOfFromPropNameInUnionType.ts, 7, 22))
|
||||
>A : Symbol(A, Decl(typeGuardOfFromPropNameInUnionType.ts, 0, 0))
|
||||
>B : Symbol(B, Decl(typeGuardOfFromPropNameInUnionType.ts, 0, 22))
|
||||
|
||||
if ("a" in x) {
|
||||
>x : Symbol(x, Decl(typeGuardOfFromPropNameInUnionType.ts, 7, 22))
|
||||
|
||||
x.a = "1";
|
||||
>x.a : Symbol(A.a, Decl(typeGuardOfFromPropNameInUnionType.ts, 0, 9))
|
||||
>x : Symbol(x, Decl(typeGuardOfFromPropNameInUnionType.ts, 7, 22))
|
||||
>a : Symbol(A.a, Decl(typeGuardOfFromPropNameInUnionType.ts, 0, 9))
|
||||
|
||||
} else {
|
||||
x.b = 1;
|
||||
>x.b : Symbol(B.b, Decl(typeGuardOfFromPropNameInUnionType.ts, 1, 9))
|
||||
>x : Symbol(x, Decl(typeGuardOfFromPropNameInUnionType.ts, 7, 22))
|
||||
>b : Symbol(B.b, Decl(typeGuardOfFromPropNameInUnionType.ts, 1, 9))
|
||||
}
|
||||
}
|
||||
|
||||
function multipleClasses(x: A | B | C | D) {
|
||||
>multipleClasses : Symbol(multipleClasses, Decl(typeGuardOfFromPropNameInUnionType.ts, 13, 1))
|
||||
>x : Symbol(x, Decl(typeGuardOfFromPropNameInUnionType.ts, 15, 25))
|
||||
>A : Symbol(A, Decl(typeGuardOfFromPropNameInUnionType.ts, 0, 0))
|
||||
>B : Symbol(B, Decl(typeGuardOfFromPropNameInUnionType.ts, 0, 22))
|
||||
>C : Symbol(C, Decl(typeGuardOfFromPropNameInUnionType.ts, 1, 22))
|
||||
>D : Symbol(D, Decl(typeGuardOfFromPropNameInUnionType.ts, 2, 22))
|
||||
|
||||
if ("a" in x) {
|
||||
>x : Symbol(x, Decl(typeGuardOfFromPropNameInUnionType.ts, 15, 25))
|
||||
|
||||
let y: string | Date = x.a;
|
||||
>y : Symbol(y, Decl(typeGuardOfFromPropNameInUnionType.ts, 17, 11))
|
||||
>Date : Symbol(Date, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>x.a : Symbol(a, Decl(typeGuardOfFromPropNameInUnionType.ts, 0, 9), Decl(typeGuardOfFromPropNameInUnionType.ts, 3, 9))
|
||||
>x : Symbol(x, Decl(typeGuardOfFromPropNameInUnionType.ts, 15, 25))
|
||||
>a : Symbol(a, Decl(typeGuardOfFromPropNameInUnionType.ts, 0, 9), Decl(typeGuardOfFromPropNameInUnionType.ts, 3, 9))
|
||||
|
||||
} else {
|
||||
let z: number | Object = x.b;
|
||||
>z : Symbol(z, Decl(typeGuardOfFromPropNameInUnionType.ts, 19, 11))
|
||||
>Object : Symbol(Object, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>x.b : Symbol(b, Decl(typeGuardOfFromPropNameInUnionType.ts, 1, 9), Decl(typeGuardOfFromPropNameInUnionType.ts, 2, 9))
|
||||
>x : Symbol(x, Decl(typeGuardOfFromPropNameInUnionType.ts, 15, 25))
|
||||
>b : Symbol(b, Decl(typeGuardOfFromPropNameInUnionType.ts, 1, 9), Decl(typeGuardOfFromPropNameInUnionType.ts, 2, 9))
|
||||
}
|
||||
}
|
||||
|
||||
function anonymousClasses(x: { a: string; } | { b: number; }) {
|
||||
>anonymousClasses : Symbol(anonymousClasses, Decl(typeGuardOfFromPropNameInUnionType.ts, 21, 1))
|
||||
>x : Symbol(x, Decl(typeGuardOfFromPropNameInUnionType.ts, 23, 26))
|
||||
>a : Symbol(a, Decl(typeGuardOfFromPropNameInUnionType.ts, 23, 30))
|
||||
>b : Symbol(b, Decl(typeGuardOfFromPropNameInUnionType.ts, 23, 47))
|
||||
|
||||
if ("a" in x) {
|
||||
>x : Symbol(x, Decl(typeGuardOfFromPropNameInUnionType.ts, 23, 26))
|
||||
|
||||
let y: string = x.a;
|
||||
>y : Symbol(y, Decl(typeGuardOfFromPropNameInUnionType.ts, 25, 11))
|
||||
>x.a : Symbol(a, Decl(typeGuardOfFromPropNameInUnionType.ts, 23, 30))
|
||||
>x : Symbol(x, Decl(typeGuardOfFromPropNameInUnionType.ts, 23, 26))
|
||||
>a : Symbol(a, Decl(typeGuardOfFromPropNameInUnionType.ts, 23, 30))
|
||||
|
||||
} else {
|
||||
let z: number = x.b;
|
||||
>z : Symbol(z, Decl(typeGuardOfFromPropNameInUnionType.ts, 27, 11))
|
||||
>x.b : Symbol(b, Decl(typeGuardOfFromPropNameInUnionType.ts, 23, 47))
|
||||
>x : Symbol(x, Decl(typeGuardOfFromPropNameInUnionType.ts, 23, 26))
|
||||
>b : Symbol(b, Decl(typeGuardOfFromPropNameInUnionType.ts, 23, 47))
|
||||
}
|
||||
}
|
||||
function inParenthesizedExpression(x: A | B) {
|
||||
>inParenthesizedExpression : Symbol(inParenthesizedExpression, Decl(typeGuardOfFromPropNameInUnionType.ts, 29, 1))
|
||||
>x : Symbol(x, Decl(typeGuardOfFromPropNameInUnionType.ts, 30, 35))
|
||||
>A : Symbol(A, Decl(typeGuardOfFromPropNameInUnionType.ts, 0, 0))
|
||||
>B : Symbol(B, Decl(typeGuardOfFromPropNameInUnionType.ts, 0, 22))
|
||||
|
||||
if ("a" in (x)) {
|
||||
>x : Symbol(x, Decl(typeGuardOfFromPropNameInUnionType.ts, 30, 35))
|
||||
|
||||
let y: string = x.a;
|
||||
>y : Symbol(y, Decl(typeGuardOfFromPropNameInUnionType.ts, 32, 11))
|
||||
>x.a : Symbol(A.a, Decl(typeGuardOfFromPropNameInUnionType.ts, 0, 9))
|
||||
>x : Symbol(x, Decl(typeGuardOfFromPropNameInUnionType.ts, 30, 35))
|
||||
>a : Symbol(A.a, Decl(typeGuardOfFromPropNameInUnionType.ts, 0, 9))
|
||||
|
||||
} else {
|
||||
let z: number = x.b;
|
||||
>z : Symbol(z, Decl(typeGuardOfFromPropNameInUnionType.ts, 34, 11))
|
||||
>x.b : Symbol(B.b, Decl(typeGuardOfFromPropNameInUnionType.ts, 1, 9))
|
||||
>x : Symbol(x, Decl(typeGuardOfFromPropNameInUnionType.ts, 30, 35))
|
||||
>b : Symbol(B.b, Decl(typeGuardOfFromPropNameInUnionType.ts, 1, 9))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function inProperty(x: ClassWithProp) {
|
||||
>inProperty : Symbol(inProperty, Decl(typeGuardOfFromPropNameInUnionType.ts, 36, 1))
|
||||
>x : Symbol(x, Decl(typeGuardOfFromPropNameInUnionType.ts, 39, 20))
|
||||
>ClassWithProp : Symbol(ClassWithProp, Decl(typeGuardOfFromPropNameInUnionType.ts, 3, 20))
|
||||
|
||||
if ("a" in x.prop) {
|
||||
>x.prop : Symbol(ClassWithProp.prop, Decl(typeGuardOfFromPropNameInUnionType.ts, 4, 21))
|
||||
>x : Symbol(x, Decl(typeGuardOfFromPropNameInUnionType.ts, 39, 20))
|
||||
>prop : Symbol(ClassWithProp.prop, Decl(typeGuardOfFromPropNameInUnionType.ts, 4, 21))
|
||||
|
||||
let y: string = x.prop.a;
|
||||
>y : Symbol(y, Decl(typeGuardOfFromPropNameInUnionType.ts, 41, 11))
|
||||
>x.prop.a : Symbol(A.a, Decl(typeGuardOfFromPropNameInUnionType.ts, 0, 9))
|
||||
>x.prop : Symbol(ClassWithProp.prop, Decl(typeGuardOfFromPropNameInUnionType.ts, 4, 21))
|
||||
>x : Symbol(x, Decl(typeGuardOfFromPropNameInUnionType.ts, 39, 20))
|
||||
>prop : Symbol(ClassWithProp.prop, Decl(typeGuardOfFromPropNameInUnionType.ts, 4, 21))
|
||||
>a : Symbol(A.a, Decl(typeGuardOfFromPropNameInUnionType.ts, 0, 9))
|
||||
|
||||
} else {
|
||||
let z: number = x.prop.b;
|
||||
>z : Symbol(z, Decl(typeGuardOfFromPropNameInUnionType.ts, 43, 11))
|
||||
>x.prop.b : Symbol(B.b, Decl(typeGuardOfFromPropNameInUnionType.ts, 1, 9))
|
||||
>x.prop : Symbol(ClassWithProp.prop, Decl(typeGuardOfFromPropNameInUnionType.ts, 4, 21))
|
||||
>x : Symbol(x, Decl(typeGuardOfFromPropNameInUnionType.ts, 39, 20))
|
||||
>prop : Symbol(ClassWithProp.prop, Decl(typeGuardOfFromPropNameInUnionType.ts, 4, 21))
|
||||
>b : Symbol(B.b, Decl(typeGuardOfFromPropNameInUnionType.ts, 1, 9))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function innestedProperty(x: NestedClassWithProp) {
|
||||
>innestedProperty : Symbol(innestedProperty, Decl(typeGuardOfFromPropNameInUnionType.ts, 45, 1))
|
||||
>x : Symbol(x, Decl(typeGuardOfFromPropNameInUnionType.ts, 48, 26))
|
||||
>NestedClassWithProp : Symbol(NestedClassWithProp, Decl(typeGuardOfFromPropNameInUnionType.ts, 4, 35))
|
||||
|
||||
if ("a" in x.outer.prop) {
|
||||
>x.outer.prop : Symbol(ClassWithProp.prop, Decl(typeGuardOfFromPropNameInUnionType.ts, 4, 21))
|
||||
>x.outer : Symbol(NestedClassWithProp.outer, Decl(typeGuardOfFromPropNameInUnionType.ts, 5, 27))
|
||||
>x : Symbol(x, Decl(typeGuardOfFromPropNameInUnionType.ts, 48, 26))
|
||||
>outer : Symbol(NestedClassWithProp.outer, Decl(typeGuardOfFromPropNameInUnionType.ts, 5, 27))
|
||||
>prop : Symbol(ClassWithProp.prop, Decl(typeGuardOfFromPropNameInUnionType.ts, 4, 21))
|
||||
|
||||
let y: string = x.outer.prop.a;
|
||||
>y : Symbol(y, Decl(typeGuardOfFromPropNameInUnionType.ts, 50, 11))
|
||||
>x.outer.prop.a : Symbol(A.a, Decl(typeGuardOfFromPropNameInUnionType.ts, 0, 9))
|
||||
>x.outer.prop : Symbol(ClassWithProp.prop, Decl(typeGuardOfFromPropNameInUnionType.ts, 4, 21))
|
||||
>x.outer : Symbol(NestedClassWithProp.outer, Decl(typeGuardOfFromPropNameInUnionType.ts, 5, 27))
|
||||
>x : Symbol(x, Decl(typeGuardOfFromPropNameInUnionType.ts, 48, 26))
|
||||
>outer : Symbol(NestedClassWithProp.outer, Decl(typeGuardOfFromPropNameInUnionType.ts, 5, 27))
|
||||
>prop : Symbol(ClassWithProp.prop, Decl(typeGuardOfFromPropNameInUnionType.ts, 4, 21))
|
||||
>a : Symbol(A.a, Decl(typeGuardOfFromPropNameInUnionType.ts, 0, 9))
|
||||
|
||||
} else {
|
||||
let z: number = x.outer.prop.b;
|
||||
>z : Symbol(z, Decl(typeGuardOfFromPropNameInUnionType.ts, 52, 11))
|
||||
>x.outer.prop.b : Symbol(B.b, Decl(typeGuardOfFromPropNameInUnionType.ts, 1, 9))
|
||||
>x.outer.prop : Symbol(ClassWithProp.prop, Decl(typeGuardOfFromPropNameInUnionType.ts, 4, 21))
|
||||
>x.outer : Symbol(NestedClassWithProp.outer, Decl(typeGuardOfFromPropNameInUnionType.ts, 5, 27))
|
||||
>x : Symbol(x, Decl(typeGuardOfFromPropNameInUnionType.ts, 48, 26))
|
||||
>outer : Symbol(NestedClassWithProp.outer, Decl(typeGuardOfFromPropNameInUnionType.ts, 5, 27))
|
||||
>prop : Symbol(ClassWithProp.prop, Decl(typeGuardOfFromPropNameInUnionType.ts, 4, 21))
|
||||
>b : Symbol(B.b, Decl(typeGuardOfFromPropNameInUnionType.ts, 1, 9))
|
||||
}
|
||||
}
|
||||
|
||||
class InMemberOfClass {
|
||||
>InMemberOfClass : Symbol(InMemberOfClass, Decl(typeGuardOfFromPropNameInUnionType.ts, 54, 1))
|
||||
|
||||
protected prop: A | B;
|
||||
>prop : Symbol(InMemberOfClass.prop, Decl(typeGuardOfFromPropNameInUnionType.ts, 56, 23))
|
||||
>A : Symbol(A, Decl(typeGuardOfFromPropNameInUnionType.ts, 0, 0))
|
||||
>B : Symbol(B, Decl(typeGuardOfFromPropNameInUnionType.ts, 0, 22))
|
||||
|
||||
inThis() {
|
||||
>inThis : Symbol(InMemberOfClass.inThis, Decl(typeGuardOfFromPropNameInUnionType.ts, 57, 26))
|
||||
|
||||
if ('a' in this.prop) {
|
||||
>this.prop : Symbol(InMemberOfClass.prop, Decl(typeGuardOfFromPropNameInUnionType.ts, 56, 23))
|
||||
>this : Symbol(InMemberOfClass, Decl(typeGuardOfFromPropNameInUnionType.ts, 54, 1))
|
||||
>prop : Symbol(InMemberOfClass.prop, Decl(typeGuardOfFromPropNameInUnionType.ts, 56, 23))
|
||||
|
||||
let y: string = this.prop.a;
|
||||
>y : Symbol(y, Decl(typeGuardOfFromPropNameInUnionType.ts, 60, 15))
|
||||
>this.prop.a : Symbol(A.a, Decl(typeGuardOfFromPropNameInUnionType.ts, 0, 9))
|
||||
>this.prop : Symbol(InMemberOfClass.prop, Decl(typeGuardOfFromPropNameInUnionType.ts, 56, 23))
|
||||
>this : Symbol(InMemberOfClass, Decl(typeGuardOfFromPropNameInUnionType.ts, 54, 1))
|
||||
>prop : Symbol(InMemberOfClass.prop, Decl(typeGuardOfFromPropNameInUnionType.ts, 56, 23))
|
||||
>a : Symbol(A.a, Decl(typeGuardOfFromPropNameInUnionType.ts, 0, 9))
|
||||
|
||||
} else {
|
||||
let z: number = this.prop.b;
|
||||
>z : Symbol(z, Decl(typeGuardOfFromPropNameInUnionType.ts, 62, 15))
|
||||
>this.prop.b : Symbol(B.b, Decl(typeGuardOfFromPropNameInUnionType.ts, 1, 9))
|
||||
>this.prop : Symbol(InMemberOfClass.prop, Decl(typeGuardOfFromPropNameInUnionType.ts, 56, 23))
|
||||
>this : Symbol(InMemberOfClass, Decl(typeGuardOfFromPropNameInUnionType.ts, 54, 1))
|
||||
>prop : Symbol(InMemberOfClass.prop, Decl(typeGuardOfFromPropNameInUnionType.ts, 56, 23))
|
||||
>b : Symbol(B.b, Decl(typeGuardOfFromPropNameInUnionType.ts, 1, 9))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//added for completeness
|
||||
class SelfAssert {
|
||||
>SelfAssert : Symbol(SelfAssert, Decl(typeGuardOfFromPropNameInUnionType.ts, 65, 1))
|
||||
|
||||
a: string;
|
||||
>a : Symbol(SelfAssert.a, Decl(typeGuardOfFromPropNameInUnionType.ts, 68, 18))
|
||||
|
||||
inThis() {
|
||||
>inThis : Symbol(SelfAssert.inThis, Decl(typeGuardOfFromPropNameInUnionType.ts, 69, 14))
|
||||
|
||||
if ('a' in this) {
|
||||
>this : Symbol(SelfAssert, Decl(typeGuardOfFromPropNameInUnionType.ts, 65, 1))
|
||||
|
||||
let y: string = this.a;
|
||||
>y : Symbol(y, Decl(typeGuardOfFromPropNameInUnionType.ts, 72, 15))
|
||||
>this.a : Symbol(SelfAssert.a, Decl(typeGuardOfFromPropNameInUnionType.ts, 68, 18))
|
||||
>this : Symbol(SelfAssert, Decl(typeGuardOfFromPropNameInUnionType.ts, 65, 1))
|
||||
>a : Symbol(SelfAssert.a, Decl(typeGuardOfFromPropNameInUnionType.ts, 68, 18))
|
||||
|
||||
} else {
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,273 @@
|
||||
=== tests/cases/conformance/expressions/typeGuards/typeGuardOfFromPropNameInUnionType.ts ===
|
||||
class A { a: string; }
|
||||
>A : A
|
||||
>a : string
|
||||
|
||||
class B { b: number; }
|
||||
>B : B
|
||||
>b : number
|
||||
|
||||
class C { b: Object; }
|
||||
>C : C
|
||||
>b : Object
|
||||
>Object : Object
|
||||
|
||||
class D { a: Date; }
|
||||
>D : D
|
||||
>a : Date
|
||||
>Date : Date
|
||||
|
||||
class ClassWithProp { prop: A | B }
|
||||
>ClassWithProp : ClassWithProp
|
||||
>prop : A | B
|
||||
>A : A
|
||||
>B : B
|
||||
|
||||
class NestedClassWithProp { outer: ClassWithProp }
|
||||
>NestedClassWithProp : NestedClassWithProp
|
||||
>outer : ClassWithProp
|
||||
>ClassWithProp : ClassWithProp
|
||||
|
||||
function namedClasses(x: A | B) {
|
||||
>namedClasses : (x: A | B) => void
|
||||
>x : A | B
|
||||
>A : A
|
||||
>B : B
|
||||
|
||||
if ("a" in x) {
|
||||
>"a" in x : boolean
|
||||
>"a" : "a"
|
||||
>x : A | B
|
||||
|
||||
x.a = "1";
|
||||
>x.a = "1" : "1"
|
||||
>x.a : string
|
||||
>x : A
|
||||
>a : string
|
||||
>"1" : "1"
|
||||
|
||||
} else {
|
||||
x.b = 1;
|
||||
>x.b = 1 : 1
|
||||
>x.b : number
|
||||
>x : B
|
||||
>b : number
|
||||
>1 : 1
|
||||
}
|
||||
}
|
||||
|
||||
function multipleClasses(x: A | B | C | D) {
|
||||
>multipleClasses : (x: A | B | C | D) => void
|
||||
>x : A | B | C | D
|
||||
>A : A
|
||||
>B : B
|
||||
>C : C
|
||||
>D : D
|
||||
|
||||
if ("a" in x) {
|
||||
>"a" in x : boolean
|
||||
>"a" : "a"
|
||||
>x : A | B | C | D
|
||||
|
||||
let y: string | Date = x.a;
|
||||
>y : string | Date
|
||||
>Date : Date
|
||||
>x.a : string | Date
|
||||
>x : A | D
|
||||
>a : string | Date
|
||||
|
||||
} else {
|
||||
let z: number | Object = x.b;
|
||||
>z : number | Object
|
||||
>Object : Object
|
||||
>x.b : number | Object
|
||||
>x : B | C
|
||||
>b : number | Object
|
||||
}
|
||||
}
|
||||
|
||||
function anonymousClasses(x: { a: string; } | { b: number; }) {
|
||||
>anonymousClasses : (x: { a: string; } | { b: number; }) => void
|
||||
>x : { a: string; } | { b: number; }
|
||||
>a : string
|
||||
>b : number
|
||||
|
||||
if ("a" in x) {
|
||||
>"a" in x : boolean
|
||||
>"a" : "a"
|
||||
>x : { a: string; } | { b: number; }
|
||||
|
||||
let y: string = x.a;
|
||||
>y : string
|
||||
>x.a : string
|
||||
>x : { a: string; }
|
||||
>a : string
|
||||
|
||||
} else {
|
||||
let z: number = x.b;
|
||||
>z : number
|
||||
>x.b : number
|
||||
>x : { b: number; }
|
||||
>b : number
|
||||
}
|
||||
}
|
||||
function inParenthesizedExpression(x: A | B) {
|
||||
>inParenthesizedExpression : (x: A | B) => void
|
||||
>x : A | B
|
||||
>A : A
|
||||
>B : B
|
||||
|
||||
if ("a" in (x)) {
|
||||
>"a" in (x) : boolean
|
||||
>"a" : "a"
|
||||
>(x) : A | B
|
||||
>x : A | B
|
||||
|
||||
let y: string = x.a;
|
||||
>y : string
|
||||
>x.a : string
|
||||
>x : A
|
||||
>a : string
|
||||
|
||||
} else {
|
||||
let z: number = x.b;
|
||||
>z : number
|
||||
>x.b : number
|
||||
>x : B
|
||||
>b : number
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function inProperty(x: ClassWithProp) {
|
||||
>inProperty : (x: ClassWithProp) => void
|
||||
>x : ClassWithProp
|
||||
>ClassWithProp : ClassWithProp
|
||||
|
||||
if ("a" in x.prop) {
|
||||
>"a" in x.prop : boolean
|
||||
>"a" : "a"
|
||||
>x.prop : A | B
|
||||
>x : ClassWithProp
|
||||
>prop : A | B
|
||||
|
||||
let y: string = x.prop.a;
|
||||
>y : string
|
||||
>x.prop.a : string
|
||||
>x.prop : A
|
||||
>x : ClassWithProp
|
||||
>prop : A
|
||||
>a : string
|
||||
|
||||
} else {
|
||||
let z: number = x.prop.b;
|
||||
>z : number
|
||||
>x.prop.b : number
|
||||
>x.prop : B
|
||||
>x : ClassWithProp
|
||||
>prop : B
|
||||
>b : number
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function innestedProperty(x: NestedClassWithProp) {
|
||||
>innestedProperty : (x: NestedClassWithProp) => void
|
||||
>x : NestedClassWithProp
|
||||
>NestedClassWithProp : NestedClassWithProp
|
||||
|
||||
if ("a" in x.outer.prop) {
|
||||
>"a" in x.outer.prop : boolean
|
||||
>"a" : "a"
|
||||
>x.outer.prop : A | B
|
||||
>x.outer : ClassWithProp
|
||||
>x : NestedClassWithProp
|
||||
>outer : ClassWithProp
|
||||
>prop : A | B
|
||||
|
||||
let y: string = x.outer.prop.a;
|
||||
>y : string
|
||||
>x.outer.prop.a : string
|
||||
>x.outer.prop : A
|
||||
>x.outer : ClassWithProp
|
||||
>x : NestedClassWithProp
|
||||
>outer : ClassWithProp
|
||||
>prop : A
|
||||
>a : string
|
||||
|
||||
} else {
|
||||
let z: number = x.outer.prop.b;
|
||||
>z : number
|
||||
>x.outer.prop.b : number
|
||||
>x.outer.prop : B
|
||||
>x.outer : ClassWithProp
|
||||
>x : NestedClassWithProp
|
||||
>outer : ClassWithProp
|
||||
>prop : B
|
||||
>b : number
|
||||
}
|
||||
}
|
||||
|
||||
class InMemberOfClass {
|
||||
>InMemberOfClass : InMemberOfClass
|
||||
|
||||
protected prop: A | B;
|
||||
>prop : A | B
|
||||
>A : A
|
||||
>B : B
|
||||
|
||||
inThis() {
|
||||
>inThis : () => void
|
||||
|
||||
if ('a' in this.prop) {
|
||||
>'a' in this.prop : boolean
|
||||
>'a' : "a"
|
||||
>this.prop : A | B
|
||||
>this : this
|
||||
>prop : A | B
|
||||
|
||||
let y: string = this.prop.a;
|
||||
>y : string
|
||||
>this.prop.a : string
|
||||
>this.prop : A
|
||||
>this : this
|
||||
>prop : A
|
||||
>a : string
|
||||
|
||||
} else {
|
||||
let z: number = this.prop.b;
|
||||
>z : number
|
||||
>this.prop.b : number
|
||||
>this.prop : B
|
||||
>this : this
|
||||
>prop : B
|
||||
>b : number
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//added for completeness
|
||||
class SelfAssert {
|
||||
>SelfAssert : SelfAssert
|
||||
|
||||
a: string;
|
||||
>a : string
|
||||
|
||||
inThis() {
|
||||
>inThis : () => void
|
||||
|
||||
if ('a' in this) {
|
||||
>'a' in this : boolean
|
||||
>'a' : "a"
|
||||
>this : this
|
||||
|
||||
let y: string = this.a;
|
||||
>y : string
|
||||
>this.a : string
|
||||
>this : this
|
||||
>a : string
|
||||
|
||||
} else {
|
||||
}
|
||||
}
|
||||
}
|
||||
97
tests/cases/compiler/inKeywordTypeguard.ts
Normal file
97
tests/cases/compiler/inKeywordTypeguard.ts
Normal file
@ -0,0 +1,97 @@
|
||||
class A { a: string; }
|
||||
class B { b: string; }
|
||||
|
||||
function negativeClassesTest(x: A | B) {
|
||||
if ("a" in x) {
|
||||
x.b = "1";
|
||||
} else {
|
||||
x.a = "1";
|
||||
}
|
||||
}
|
||||
|
||||
function positiveClassesTest(x: A | B) {
|
||||
if ("a" in x) {
|
||||
x.b = "1";
|
||||
} else {
|
||||
x.a = "1";
|
||||
}
|
||||
}
|
||||
|
||||
class AOpt { a?: string }
|
||||
class BOpn { b?: string }
|
||||
|
||||
function positiveTestClassesWithOptionalProperties(x: AOpt | BOpn) {
|
||||
if ("a" in x) {
|
||||
x.a = "1";
|
||||
} else {
|
||||
x.b = "1";
|
||||
}
|
||||
}
|
||||
|
||||
class AWithMethod {
|
||||
a(): string { return "" }
|
||||
}
|
||||
|
||||
class BWithMethod {
|
||||
b(): string { return "" }
|
||||
}
|
||||
|
||||
function negativeTestClassesWithMembers(x: AWithMethod | BWithMethod) {
|
||||
if ("a" in x) {
|
||||
x.a();
|
||||
x.b();
|
||||
} else {
|
||||
}
|
||||
}
|
||||
|
||||
function negativeTestClassesWithMemberMissingInBothClasses(x: AWithMethod | BWithMethod) {
|
||||
if ("c" in x) {
|
||||
x.a();
|
||||
x.b();
|
||||
} else {
|
||||
x.a();
|
||||
x.b();
|
||||
}
|
||||
}
|
||||
|
||||
class C { a: string }
|
||||
class D { a: string }
|
||||
|
||||
function negativeMultipleClassesTest(x: A | B | C | D) {
|
||||
if ("a" in x) {
|
||||
x.b = "1";
|
||||
} else {
|
||||
x.a = "1";
|
||||
}
|
||||
}
|
||||
|
||||
class ClassWithProp { prop: A | B }
|
||||
|
||||
function negativePropTest(x: ClassWithProp) {
|
||||
if ("a" in x.prop) {
|
||||
let y: string = x.prop.b;
|
||||
} else {
|
||||
let z: string = x.prop.a;
|
||||
}
|
||||
}
|
||||
|
||||
class NegativeClassTest {
|
||||
protected prop: A | B;
|
||||
inThis() {
|
||||
if ('a' in this.prop) {
|
||||
let z: number = this.prop.b;
|
||||
} else {
|
||||
let y: string = this.prop.a;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class UnreachableCodeDetection {
|
||||
a: string;
|
||||
inThis() {
|
||||
if ('a' in this) {
|
||||
} else {
|
||||
let y = this.a;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,77 @@
|
||||
class A { a: string; }
|
||||
class B { b: number; }
|
||||
class C { b: Object; }
|
||||
class D { a: Date; }
|
||||
class ClassWithProp { prop: A | B }
|
||||
class NestedClassWithProp { outer: ClassWithProp }
|
||||
|
||||
function namedClasses(x: A | B) {
|
||||
if ("a" in x) {
|
||||
x.a = "1";
|
||||
} else {
|
||||
x.b = 1;
|
||||
}
|
||||
}
|
||||
|
||||
function multipleClasses(x: A | B | C | D) {
|
||||
if ("a" in x) {
|
||||
let y: string | Date = x.a;
|
||||
} else {
|
||||
let z: number | Object = x.b;
|
||||
}
|
||||
}
|
||||
|
||||
function anonymousClasses(x: { a: string; } | { b: number; }) {
|
||||
if ("a" in x) {
|
||||
let y: string = x.a;
|
||||
} else {
|
||||
let z: number = x.b;
|
||||
}
|
||||
}
|
||||
function inParenthesizedExpression(x: A | B) {
|
||||
if ("a" in (x)) {
|
||||
let y: string = x.a;
|
||||
} else {
|
||||
let z: number = x.b;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function inProperty(x: ClassWithProp) {
|
||||
if ("a" in x.prop) {
|
||||
let y: string = x.prop.a;
|
||||
} else {
|
||||
let z: number = x.prop.b;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function innestedProperty(x: NestedClassWithProp) {
|
||||
if ("a" in x.outer.prop) {
|
||||
let y: string = x.outer.prop.a;
|
||||
} else {
|
||||
let z: number = x.outer.prop.b;
|
||||
}
|
||||
}
|
||||
|
||||
class InMemberOfClass {
|
||||
protected prop: A | B;
|
||||
inThis() {
|
||||
if ('a' in this.prop) {
|
||||
let y: string = this.prop.a;
|
||||
} else {
|
||||
let z: number = this.prop.b;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//added for completeness
|
||||
class SelfAssert {
|
||||
a: string;
|
||||
inThis() {
|
||||
if ('a' in this) {
|
||||
let y: string = this.a;
|
||||
} else {
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user