From 52a8e2687e55e067f4b0d1dc10444e54c29de093 Mon Sep 17 00:00:00 2001 From: ShuiRuTian <158983297@qq.com> Date: Sun, 7 Jun 2020 15:34:03 +0800 Subject: [PATCH] add test cases --- src/compiler/checker.ts | 19 +- .../reference/typeGuardAccordingToProperty.js | 1 + .../typeGuardAccordingToPropertyBySwitch.js | 1 + .../typeGuardAccordingToPropertyDeep.js | 1 + ...uardAccordingToPropertyOptional.errors.txt | 154 ++++++++++ .../typeGuardAccordingToPropertyOptional.js | 17 ++ ...peGuardAccordingToPropertyOptional.symbols | 74 ++++- ...typeGuardAccordingToPropertyOptional.types | 262 +++++++++++------- .../typeGuardAccordingToProperty.ts | 2 +- .../typeGuardAccordingToPropertyBySwitch.ts | 1 + .../typeGuardAccordingToPropertyDeep.ts | 2 +- .../typeGuardAccordingToPropertyOptional.ts | 10 + 12 files changed, 416 insertions(+), 128 deletions(-) create mode 100644 tests/baselines/reference/typeGuardAccordingToPropertyOptional.errors.txt diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index d9dda67e02665..747166f94eb65 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -21203,7 +21203,8 @@ namespace ts { let notNullOrUndefinedFilter = false; // the aim of this filter is type has 'undefined',filter it out from result. const isExpressionContainOptionalChain = isAccessExpressionContainOptionalChain(typeOfExpr.expression); // ~undefined means other values except undefiend. boolean, bigint.... - if (assumeTrue && literal.text !== "undefined") { + if ((assumeTrue && literal.text !== "undefined")||(!assumeTrue && literal.text === "undefined")) { + // !== undefined // === ~undefined // use full expression to narrow propertyTypeArray = narrowUnionTypeWithPropertyPathAndExpression(type, typeOfExpr.expression,/* optionalChainSlice */ false); @@ -21213,10 +21214,6 @@ namespace ts { // !== ~undefined, === undefined, !==undefined // use non-OptionalChain part to narrow propertyTypeArray = narrowUnionTypeWithPropertyPathAndExpression(type, typeOfExpr.expression,/* optionalChainSlice */ true); - if (!assumeTrue && literal.text === "undefined") { - // !== undefined - notNullOrUndefinedFilter = true; - } if (isExpressionContainOptionalChain) { facts = TypeFacts.None; // The aim is no filter. } @@ -29673,12 +29670,12 @@ namespace ts { } // If a type has been cached for the node, return it. // Note: this is not only cache, without this, some test case would always runs, such as binaryArithmeticControlFlowGraphNotTooLarge. - if (node.flags & NodeFlags.TypeCached && flowTypeCache) { - const cachedType = flowTypeCache[getNodeId(node)]; - if (cachedType) { - return cachedType; - } - } + // if (node.flags & NodeFlags.TypeCached && flowTypeCache) { + // const cachedType = flowTypeCache[getNodeId(node)]; + // if (cachedType) { + // return cachedType; + // } + // } const startInvocationCount = flowInvocationCount; const type = checkExpression(node); // If control flow analysis was required to determine the type, it is worth caching. diff --git a/tests/baselines/reference/typeGuardAccordingToProperty.js b/tests/baselines/reference/typeGuardAccordingToProperty.js index cef8519f743db..e94f56967ad59 100644 --- a/tests/baselines/reference/typeGuardAccordingToProperty.js +++ b/tests/baselines/reference/typeGuardAccordingToProperty.js @@ -269,6 +269,7 @@ function f1_(u: Union1) { //// [typeGuardAccordingToProperty.js] +"use strict"; // Primitive value ---- boolean bigint number string symbol undefined function object // ts special type ---- any, void, unknown, union, intersection ; diff --git a/tests/baselines/reference/typeGuardAccordingToPropertyBySwitch.js b/tests/baselines/reference/typeGuardAccordingToPropertyBySwitch.js index 6e3dee9024b3f..21374f1254770 100644 --- a/tests/baselines/reference/typeGuardAccordingToPropertyBySwitch.js +++ b/tests/baselines/reference/typeGuardAccordingToPropertyBySwitch.js @@ -48,6 +48,7 @@ function f2(u: Union2) { //// [typeGuardAccordingToPropertyBySwitch.js] +"use strict"; function f(u) { switch (typeof u.firstKey) { case 'number': diff --git a/tests/baselines/reference/typeGuardAccordingToPropertyDeep.js b/tests/baselines/reference/typeGuardAccordingToPropertyDeep.js index c504bccd64817..6c252eca2d364 100644 --- a/tests/baselines/reference/typeGuardAccordingToPropertyDeep.js +++ b/tests/baselines/reference/typeGuardAccordingToPropertyDeep.js @@ -55,6 +55,7 @@ function f4(u: Union2) { //// [typeGuardAccordingToPropertyDeep.js] +"use strict"; //// deep property access ---- a.b.c.d.e.f, a["b"]["c"]["d"] //// mix deep property access ---- a.b["c"]["d"].e function f(u) { diff --git a/tests/baselines/reference/typeGuardAccordingToPropertyOptional.errors.txt b/tests/baselines/reference/typeGuardAccordingToPropertyOptional.errors.txt new file mode 100644 index 0000000000000..dbf0794efe017 --- /dev/null +++ b/tests/baselines/reference/typeGuardAccordingToPropertyOptional.errors.txt @@ -0,0 +1,154 @@ +tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToPropertyOptional.ts(64,9): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToPropertyOptional.ts(72,9): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToPropertyOptional.ts(84,9): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToPropertyOptional.ts(84,9): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToPropertyOptional.ts(88,11): error TS2339: Property 'key1' does not exist on type 'never'. +tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToPropertyOptional.ts(96,9): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToPropertyOptional.ts(96,9): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToPropertyOptional.ts(103,9): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToPropertyOptional.ts(103,9): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToPropertyOptional.ts(115,9): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToPropertyOptional.ts(115,9): error TS2532: Object is possibly 'undefined'. + + +==== tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToPropertyOptional.ts (11 errors) ==== + interface Foo1 { + key1:{ + key2:number; + }|undefined; + f1: number; + } + + interface Foo2 { + key1: { + key2:string + } | undefined; + f2: number; + } + + interface Foo3 { + key1:{ + key2:number; + }; + f2: number; + } + + type U1 = Foo1 | Foo2 | Foo3; + type U2 = Foo1 | Foo2 | Foo3|undefined; + + // unnecessary optional chain + function f1(u: U1) { + if (typeof u?.key1 !== 'number') { + u; // U1 + } + if (typeof u?.key1 === 'number') { + u; // never + } + if (typeof u?.key1 !== 'undefined') { + u; // U1 + } + if (typeof u?.key1 === 'undefined') { + u; // U1 + } + } + + // non-root optional chain + function f2(u: U1) { + if (typeof u.key1?.key2 !== 'number') { + u; // U1 + } + if (typeof u.key1?.key2 === 'number') { + u; // Foo1 | Foo3 + } + if (typeof u.key1?.key2 !== 'undefined') { + u; // U1 + } + if (typeof u.key1?.key2 === 'undefined') { + u; // U1 + } + } + + function f2Plus(u: U1){ + if (typeof u.key1?.key2 === 'undefined' && typeof u.key1?.key2 === 'number') { + u; // Foo1 | Foo3 + u.key1.key2; + } + if (typeof u.key1?.key2 === 'undefined' || typeof u.key1?.key2 === 'number') { + u; // U1 + u.key1.key2; // Error + ~~~~~~ +!!! error TS2532: Object is possibly 'undefined'. + } + if ( typeof u.key1?.key2 === 'number' && typeof u.key1?.key2 === 'undefined') { + u; // Foo1 | Foo3 + u.key1.key2; + } + if ( typeof u.key1?.key2 === 'number' || typeof u.key1?.key2 === 'undefined') { + u; // U1 + u.key1.key2; // Error + ~~~~~~ +!!! error TS2532: Object is possibly 'undefined'. + } + if ( typeof u.key1?.key2 === 'number' || typeof u.key1?.key2 !== 'undefined') { + u; // U1 + u.key1.key2; + } + } + + // root optional chain + function f3(u: U2) { + if (typeof u?.key1 !== 'number') { + u; // U2 + u.key1.key2; + ~ +!!! error TS2532: Object is possibly 'undefined'. + ~~~~~~ +!!! error TS2532: Object is possibly 'undefined'. + } + if (typeof u?.key1 === 'number') { + u; // never + u.key1.key2; + ~~~~ +!!! error TS2339: Property 'key1' does not exist on type 'never'. + } + if (typeof u?.key1 !== 'undefined') { + u; // Foo1 | Foo2 | Foo3 + u.key1.key2; + } + if (typeof u?.key1 === 'undefined') { + u; // U2 + u.key1.key2; + ~ +!!! error TS2532: Object is possibly 'undefined'. + ~~~~~~ +!!! error TS2532: Object is possibly 'undefined'. + } + } + + function f4(u: U2) { + if (typeof u?.key1?.key2 !== 'number') { + u; // U2 + u.key1.key2; + ~ +!!! error TS2532: Object is possibly 'undefined'. + ~~~~~~ +!!! error TS2532: Object is possibly 'undefined'. + } + if (typeof u?.key1?.key2 === 'number') { + u; // Foo1 | Foo3 + u.key1.key2; + } + if (typeof u?.key1?.key2 !== 'undefined') { + u; // Foo1 | Foo2 | Foo3 + u.key1.key2; + } + if (typeof u?.key1?.key2 === 'undefined') { + u; // U2 + u.key1.key2; + ~ +!!! error TS2532: Object is possibly 'undefined'. + ~~~~~~ +!!! error TS2532: Object is possibly 'undefined'. + } + } + \ No newline at end of file diff --git a/tests/baselines/reference/typeGuardAccordingToPropertyOptional.js b/tests/baselines/reference/typeGuardAccordingToPropertyOptional.js index 7e875117cf733..ffdc7e4b601c0 100644 --- a/tests/baselines/reference/typeGuardAccordingToPropertyOptional.js +++ b/tests/baselines/reference/typeGuardAccordingToPropertyOptional.js @@ -82,35 +82,44 @@ function f2Plus(u: U1){ function f3(u: U2) { if (typeof u?.key1 !== 'number') { u; // U2 + u.key1.key2; } if (typeof u?.key1 === 'number') { u; // never + u.key1.key2; } if (typeof u?.key1 !== 'undefined') { u; // Foo1 | Foo2 | Foo3 + u.key1.key2; } if (typeof u?.key1 === 'undefined') { u; // U2 + u.key1.key2; } } function f4(u: U2) { if (typeof u?.key1?.key2 !== 'number') { u; // U2 + u.key1.key2; } if (typeof u?.key1?.key2 === 'number') { u; // Foo1 | Foo3 + u.key1.key2; } if (typeof u?.key1?.key2 !== 'undefined') { u; // Foo1 | Foo2 | Foo3 + u.key1.key2; } if (typeof u?.key1?.key2 === 'undefined') { u; // U2 + u.key1.key2; } } //// [typeGuardAccordingToPropertyOptional.js] +"use strict"; // unnecessary optional chain function f1(u) { if (typeof (u === null || u === void 0 ? void 0 : u.key1) !== 'number') { @@ -169,29 +178,37 @@ function f2Plus(u) { function f3(u) { if (typeof (u === null || u === void 0 ? void 0 : u.key1) !== 'number') { u; // U2 + u.key1.key2; } if (typeof (u === null || u === void 0 ? void 0 : u.key1) === 'number') { u; // never + u.key1.key2; } if (typeof (u === null || u === void 0 ? void 0 : u.key1) !== 'undefined') { u; // Foo1 | Foo2 | Foo3 + u.key1.key2; } if (typeof (u === null || u === void 0 ? void 0 : u.key1) === 'undefined') { u; // U2 + u.key1.key2; } } function f4(u) { var _a, _b, _c, _d; if (typeof ((_a = u === null || u === void 0 ? void 0 : u.key1) === null || _a === void 0 ? void 0 : _a.key2) !== 'number') { u; // U2 + u.key1.key2; } if (typeof ((_b = u === null || u === void 0 ? void 0 : u.key1) === null || _b === void 0 ? void 0 : _b.key2) === 'number') { u; // Foo1 | Foo3 + u.key1.key2; } if (typeof ((_c = u === null || u === void 0 ? void 0 : u.key1) === null || _c === void 0 ? void 0 : _c.key2) !== 'undefined') { u; // Foo1 | Foo2 | Foo3 + u.key1.key2; } if (typeof ((_d = u === null || u === void 0 ? void 0 : u.key1) === null || _d === void 0 ? void 0 : _d.key2) === 'undefined') { u; // U2 + u.key1.key2; } } diff --git a/tests/baselines/reference/typeGuardAccordingToPropertyOptional.symbols b/tests/baselines/reference/typeGuardAccordingToPropertyOptional.symbols index c34dbf9d5735e..8763d6bc59d81 100644 --- a/tests/baselines/reference/typeGuardAccordingToPropertyOptional.symbols +++ b/tests/baselines/reference/typeGuardAccordingToPropertyOptional.symbols @@ -206,11 +206,11 @@ function f2Plus(u: U1){ >u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 56, 16)) u.key1.key2; ->u.key1.key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptional.ts, 1, 10), Decl(typeGuardAccordingToPropertyOptional.ts, 15, 10)) +>u.key1.key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptional.ts, 1, 10)) >u.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) >u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 56, 16)) >key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) ->key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptional.ts, 1, 10), Decl(typeGuardAccordingToPropertyOptional.ts, 15, 10)) +>key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptional.ts, 1, 10)) } if ( typeof u.key1?.key2 === 'number' || typeof u.key1?.key2 === 'undefined') { >u.key1?.key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptional.ts, 1, 10), Decl(typeGuardAccordingToPropertyOptional.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 15, 10)) @@ -271,6 +271,13 @@ function f3(u: U2) { u; // U2 >u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 80, 12)) + + u.key1.key2; +>u.key1.key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptional.ts, 1, 10), Decl(typeGuardAccordingToPropertyOptional.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 15, 10)) +>u.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 80, 12)) +>key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) +>key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptional.ts, 1, 10), Decl(typeGuardAccordingToPropertyOptional.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 15, 10)) } if (typeof u?.key1 === 'number') { >u?.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) @@ -279,6 +286,9 @@ function f3(u: U2) { u; // never >u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 80, 12)) + + u.key1.key2; +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 80, 12)) } if (typeof u?.key1 !== 'undefined') { >u?.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) @@ -287,6 +297,13 @@ function f3(u: U2) { u; // Foo1 | Foo2 | Foo3 >u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 80, 12)) + + u.key1.key2; +>u.key1.key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptional.ts, 1, 10), Decl(typeGuardAccordingToPropertyOptional.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 15, 10)) +>u.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 80, 12)) +>key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) +>key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptional.ts, 1, 10), Decl(typeGuardAccordingToPropertyOptional.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 15, 10)) } if (typeof u?.key1 === 'undefined') { >u?.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) @@ -295,53 +312,86 @@ function f3(u: U2) { u; // U2 >u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 80, 12)) + + u.key1.key2; +>u.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 80, 12)) +>key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) } } function f4(u: U2) { ->f4 : Symbol(f4, Decl(typeGuardAccordingToPropertyOptional.ts, 93, 1)) ->u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 95, 12)) +>f4 : Symbol(f4, Decl(typeGuardAccordingToPropertyOptional.ts, 97, 1)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 99, 12)) >U2 : Symbol(U2, Decl(typeGuardAccordingToPropertyOptional.ts, 21, 29)) if (typeof u?.key1?.key2 !== 'number') { >u?.key1?.key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptional.ts, 1, 10), Decl(typeGuardAccordingToPropertyOptional.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 15, 10)) >u?.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) ->u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 95, 12)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 99, 12)) >key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) >key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptional.ts, 1, 10), Decl(typeGuardAccordingToPropertyOptional.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 15, 10)) u; // U2 ->u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 95, 12)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 99, 12)) + + u.key1.key2; +>u.key1.key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptional.ts, 1, 10), Decl(typeGuardAccordingToPropertyOptional.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 15, 10)) +>u.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 99, 12)) +>key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) +>key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptional.ts, 1, 10), Decl(typeGuardAccordingToPropertyOptional.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 15, 10)) } if (typeof u?.key1?.key2 === 'number') { >u?.key1?.key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptional.ts, 1, 10), Decl(typeGuardAccordingToPropertyOptional.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 15, 10)) >u?.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) ->u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 95, 12)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 99, 12)) >key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) >key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptional.ts, 1, 10), Decl(typeGuardAccordingToPropertyOptional.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 15, 10)) u; // Foo1 | Foo3 ->u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 95, 12)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 99, 12)) + + u.key1.key2; +>u.key1.key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptional.ts, 1, 10), Decl(typeGuardAccordingToPropertyOptional.ts, 15, 10)) +>u.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 99, 12)) +>key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) +>key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptional.ts, 1, 10), Decl(typeGuardAccordingToPropertyOptional.ts, 15, 10)) } if (typeof u?.key1?.key2 !== 'undefined') { >u?.key1?.key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptional.ts, 1, 10), Decl(typeGuardAccordingToPropertyOptional.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 15, 10)) >u?.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) ->u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 95, 12)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 99, 12)) >key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) >key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptional.ts, 1, 10), Decl(typeGuardAccordingToPropertyOptional.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 15, 10)) u; // Foo1 | Foo2 | Foo3 ->u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 95, 12)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 99, 12)) + + u.key1.key2; +>u.key1.key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptional.ts, 1, 10), Decl(typeGuardAccordingToPropertyOptional.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 15, 10)) +>u.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 99, 12)) +>key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) +>key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptional.ts, 1, 10), Decl(typeGuardAccordingToPropertyOptional.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 15, 10)) } if (typeof u?.key1?.key2 === 'undefined') { >u?.key1?.key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptional.ts, 1, 10), Decl(typeGuardAccordingToPropertyOptional.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 15, 10)) >u?.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) ->u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 95, 12)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 99, 12)) >key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) >key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptional.ts, 1, 10), Decl(typeGuardAccordingToPropertyOptional.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 15, 10)) u; // U2 ->u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 95, 12)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 99, 12)) + + u.key1.key2; +>u.key1.key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptional.ts, 1, 10), Decl(typeGuardAccordingToPropertyOptional.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 15, 10)) +>u.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 99, 12)) +>key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) +>key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptional.ts, 1, 10), Decl(typeGuardAccordingToPropertyOptional.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 15, 10)) } } diff --git a/tests/baselines/reference/typeGuardAccordingToPropertyOptional.types b/tests/baselines/reference/typeGuardAccordingToPropertyOptional.types index 0728dba332b60..244e102f2068b 100644 --- a/tests/baselines/reference/typeGuardAccordingToPropertyOptional.types +++ b/tests/baselines/reference/typeGuardAccordingToPropertyOptional.types @@ -1,7 +1,7 @@ === tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToPropertyOptional.ts === interface Foo1 { key1:{ ->key1 : { key2: number; } +>key1 : { key2: number; } | undefined key2:number; >key2 : number @@ -13,7 +13,7 @@ interface Foo1 { interface Foo2 { key1: { ->key1 : { key2: string; } +>key1 : { key2: string; } | undefined key2:string >key2 : string @@ -39,7 +39,7 @@ type U1 = Foo1 | Foo2 | Foo3; >U1 : U1 type U2 = Foo1 | Foo2 | Foo3|undefined; ->U2 : U1 +>U2 : U2 // unnecessary optional chain function f1(u: U1) { @@ -49,9 +49,9 @@ function f1(u: U1) { if (typeof u?.key1 !== 'number') { >typeof u?.key1 !== 'number' : boolean >typeof u?.key1 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" ->u?.key1 : { key2: number; } | { key2: string; } | { key2: number; } +>u?.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined >u : U1 ->key1 : { key2: number; } | { key2: string; } | { key2: number; } +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined >'number' : "number" u; // U1 @@ -60,9 +60,9 @@ function f1(u: U1) { if (typeof u?.key1 === 'number') { >typeof u?.key1 === 'number' : boolean >typeof u?.key1 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" ->u?.key1 : { key2: number; } | { key2: string; } | { key2: number; } +>u?.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined >u : U1 ->key1 : { key2: number; } | { key2: string; } | { key2: number; } +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined >'number' : "number" u; // never @@ -71,9 +71,9 @@ function f1(u: U1) { if (typeof u?.key1 !== 'undefined') { >typeof u?.key1 !== 'undefined' : boolean >typeof u?.key1 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" ->u?.key1 : { key2: number; } | { key2: string; } | { key2: number; } +>u?.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined >u : U1 ->key1 : { key2: number; } | { key2: string; } | { key2: number; } +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined >'undefined' : "undefined" u; // U1 @@ -82,9 +82,9 @@ function f1(u: U1) { if (typeof u?.key1 === 'undefined') { >typeof u?.key1 === 'undefined' : boolean >typeof u?.key1 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" ->u?.key1 : { key2: number; } | { key2: string; } | { key2: number; } +>u?.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined >u : U1 ->key1 : { key2: number; } | { key2: string; } | { key2: number; } +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined >'undefined' : "undefined" u; // U1 @@ -100,11 +100,11 @@ function f2(u: U1) { if (typeof u.key1?.key2 !== 'number') { >typeof u.key1?.key2 !== 'number' : boolean >typeof u.key1?.key2 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" ->u.key1?.key2 : string | number ->u.key1 : { key2: number; } | { key2: string; } | { key2: number; } +>u.key1?.key2 : string | number | undefined +>u.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined >u : U1 ->key1 : { key2: number; } | { key2: string; } | { key2: number; } ->key2 : string | number +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>key2 : string | number | undefined >'number' : "number" u; // U1 @@ -113,11 +113,11 @@ function f2(u: U1) { if (typeof u.key1?.key2 === 'number') { >typeof u.key1?.key2 === 'number' : boolean >typeof u.key1?.key2 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" ->u.key1?.key2 : string | number ->u.key1 : { key2: number; } | { key2: string; } | { key2: number; } +>u.key1?.key2 : string | number | undefined +>u.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined >u : U1 ->key1 : { key2: number; } | { key2: string; } | { key2: number; } ->key2 : string | number +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>key2 : string | number | undefined >'number' : "number" u; // Foo1 | Foo3 @@ -126,11 +126,11 @@ function f2(u: U1) { if (typeof u.key1?.key2 !== 'undefined') { >typeof u.key1?.key2 !== 'undefined' : boolean >typeof u.key1?.key2 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" ->u.key1?.key2 : string | number ->u.key1 : { key2: number; } | { key2: string; } | { key2: number; } +>u.key1?.key2 : string | number | undefined +>u.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined >u : U1 ->key1 : { key2: number; } | { key2: string; } | { key2: number; } ->key2 : string | number +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>key2 : string | number | undefined >'undefined' : "undefined" u; // U1 @@ -139,11 +139,11 @@ function f2(u: U1) { if (typeof u.key1?.key2 === 'undefined') { >typeof u.key1?.key2 === 'undefined' : boolean >typeof u.key1?.key2 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" ->u.key1?.key2 : string | number ->u.key1 : { key2: number; } | { key2: string; } | { key2: number; } +>u.key1?.key2 : string | number | undefined +>u.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined >u : U1 ->key1 : { key2: number; } | { key2: string; } | { key2: number; } ->key2 : string | number +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>key2 : string | number | undefined >'undefined' : "undefined" u; // U1 @@ -159,18 +159,18 @@ function f2Plus(u: U1){ >typeof u.key1?.key2 === 'undefined' && typeof u.key1?.key2 === 'number' : boolean >typeof u.key1?.key2 === 'undefined' : boolean >typeof u.key1?.key2 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" ->u.key1?.key2 : string | number ->u.key1 : { key2: number; } | { key2: string; } | { key2: number; } +>u.key1?.key2 : string | number | undefined +>u.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined >u : U1 ->key1 : { key2: number; } | { key2: string; } | { key2: number; } ->key2 : string | number +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>key2 : string | number | undefined >'undefined' : "undefined" >typeof u.key1?.key2 === 'number' : boolean >typeof u.key1?.key2 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" >u.key1?.key2 : undefined ->u.key1 : { key2: number; } | { key2: string; } | { key2: number; } +>u.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined >u : U1 ->key1 : { key2: number; } | { key2: string; } | { key2: number; } +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined >key2 : undefined >'number' : "number" @@ -188,11 +188,11 @@ function f2Plus(u: U1){ >typeof u.key1?.key2 === 'undefined' || typeof u.key1?.key2 === 'number' : boolean >typeof u.key1?.key2 === 'undefined' : boolean >typeof u.key1?.key2 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" ->u.key1?.key2 : string | number ->u.key1 : { key2: number; } | { key2: string; } | { key2: number; } +>u.key1?.key2 : string | number | undefined +>u.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined >u : U1 ->key1 : { key2: number; } | { key2: string; } | { key2: number; } ->key2 : string | number +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>key2 : string | number | undefined >'undefined' : "undefined" >typeof u.key1?.key2 === 'number' : boolean >typeof u.key1?.key2 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" @@ -208,20 +208,20 @@ function f2Plus(u: U1){ u.key1.key2; // Error >u.key1.key2 : number ->u.key1 : { key2: number; } | { key2: string; } | { key2: number; } +>u.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined >u : U1 ->key1 : { key2: number; } | { key2: string; } | { key2: number; } +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined >key2 : number } if ( typeof u.key1?.key2 === 'number' && typeof u.key1?.key2 === 'undefined') { >typeof u.key1?.key2 === 'number' && typeof u.key1?.key2 === 'undefined' : boolean >typeof u.key1?.key2 === 'number' : boolean >typeof u.key1?.key2 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" ->u.key1?.key2 : string | number ->u.key1 : { key2: number; } | { key2: string; } | { key2: number; } +>u.key1?.key2 : string | number | undefined +>u.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined >u : U1 ->key1 : { key2: number; } | { key2: string; } | { key2: number; } ->key2 : string | number +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>key2 : string | number | undefined >'number' : "number" >typeof u.key1?.key2 === 'undefined' : boolean >typeof u.key1?.key2 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" @@ -236,29 +236,29 @@ function f2Plus(u: U1){ >u : Foo1 | Foo3 u.key1.key2; ->u.key1.key2 : undefined ->u.key1 : { key2: number; } | { key2: number; } +>u.key1.key2 : never +>u.key1 : { key2: number; } >u : Foo1 | Foo3 ->key1 : { key2: number; } | { key2: number; } ->key2 : undefined +>key1 : { key2: number; } +>key2 : never } if ( typeof u.key1?.key2 === 'number' || typeof u.key1?.key2 === 'undefined') { >typeof u.key1?.key2 === 'number' || typeof u.key1?.key2 === 'undefined' : boolean >typeof u.key1?.key2 === 'number' : boolean >typeof u.key1?.key2 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" ->u.key1?.key2 : string | number ->u.key1 : { key2: number; } | { key2: string; } | { key2: number; } +>u.key1?.key2 : string | number | undefined +>u.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined >u : U1 ->key1 : { key2: number; } | { key2: string; } | { key2: number; } ->key2 : string | number +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>key2 : string | number | undefined >'number' : "number" >typeof u.key1?.key2 === 'undefined' : boolean >typeof u.key1?.key2 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" ->u.key1?.key2 : string ->u.key1 : { key2: number; } | { key2: string; } | { key2: number; } +>u.key1?.key2 : string | undefined +>u.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined >u : U1 ->key1 : { key2: number; } | { key2: string; } | { key2: number; } ->key2 : string +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>key2 : string | undefined >'undefined' : "undefined" u; // U1 @@ -266,28 +266,28 @@ function f2Plus(u: U1){ u.key1.key2; // Error >u.key1.key2 : number ->u.key1 : { key2: number; } | { key2: string; } | { key2: number; } +>u.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined >u : U1 ->key1 : { key2: number; } | { key2: string; } | { key2: number; } +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined >key2 : number } if ( typeof u.key1?.key2 === 'number' || typeof u.key1?.key2 !== 'undefined') { >typeof u.key1?.key2 === 'number' || typeof u.key1?.key2 !== 'undefined' : boolean >typeof u.key1?.key2 === 'number' : boolean >typeof u.key1?.key2 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" ->u.key1?.key2 : string | number ->u.key1 : { key2: number; } | { key2: string; } | { key2: number; } +>u.key1?.key2 : string | number | undefined +>u.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined >u : U1 ->key1 : { key2: number; } | { key2: string; } | { key2: number; } ->key2 : string | number +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>key2 : string | number | undefined >'number' : "number" >typeof u.key1?.key2 !== 'undefined' : boolean >typeof u.key1?.key2 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" ->u.key1?.key2 : string ->u.key1 : { key2: number; } | { key2: string; } | { key2: number; } +>u.key1?.key2 : string | undefined +>u.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined >u : U1 ->key1 : { key2: number; } | { key2: string; } | { key2: number; } ->key2 : string +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>key2 : string | undefined >'undefined' : "undefined" u; // U1 @@ -305,109 +305,165 @@ function f2Plus(u: U1){ // root optional chain function f3(u: U2) { >f3 : (u: U2) => void ->u : U1 +>u : U2 if (typeof u?.key1 !== 'number') { >typeof u?.key1 !== 'number' : boolean >typeof u?.key1 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" ->u?.key1 : { key2: number; } | { key2: string; } | { key2: number; } ->u : U1 ->key1 : { key2: number; } | { key2: string; } | { key2: number; } +>u?.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>u : U2 +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined >'number' : "number" u; // U2 ->u : U1 +>u : U2 + + u.key1.key2; +>u.key1.key2 : string | number +>u.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>u : U2 +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>key2 : string | number } if (typeof u?.key1 === 'number') { >typeof u?.key1 === 'number' : boolean >typeof u?.key1 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" ->u?.key1 : { key2: number; } | { key2: string; } | { key2: number; } ->u : U1 ->key1 : { key2: number; } | { key2: string; } | { key2: number; } +>u?.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>u : U2 +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined >'number' : "number" u; // never >u : never + + u.key1.key2; +>u.key1.key2 : any +>u.key1 : any +>u : never +>key1 : any +>key2 : any } if (typeof u?.key1 !== 'undefined') { >typeof u?.key1 !== 'undefined' : boolean >typeof u?.key1 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" ->u?.key1 : { key2: number; } | { key2: string; } | { key2: number; } ->u : U1 ->key1 : { key2: number; } | { key2: string; } | { key2: number; } +>u?.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>u : U2 +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined >'undefined' : "undefined" u; // Foo1 | Foo2 | Foo3 >u : U1 + + u.key1.key2; +>u.key1.key2 : string | number +>u.key1 : { key2: number; } | { key2: string; } | { key2: number; } +>u : U1 +>key1 : { key2: number; } | { key2: string; } | { key2: number; } +>key2 : string | number } if (typeof u?.key1 === 'undefined') { >typeof u?.key1 === 'undefined' : boolean >typeof u?.key1 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" ->u?.key1 : { key2: number; } | { key2: string; } | { key2: number; } ->u : U1 ->key1 : { key2: number; } | { key2: string; } | { key2: number; } +>u?.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>u : U2 +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined >'undefined' : "undefined" u; // U2 ->u : U1 +>u : U2 + + u.key1.key2; +>u.key1.key2 : any +>u.key1 : undefined +>u : U2 +>key1 : undefined +>key2 : any } } function f4(u: U2) { >f4 : (u: U2) => void ->u : U1 +>u : U2 if (typeof u?.key1?.key2 !== 'number') { >typeof u?.key1?.key2 !== 'number' : boolean >typeof u?.key1?.key2 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" ->u?.key1?.key2 : string | number ->u?.key1 : { key2: number; } | { key2: string; } | { key2: number; } ->u : U1 ->key1 : { key2: number; } | { key2: string; } | { key2: number; } ->key2 : string | number +>u?.key1?.key2 : string | number | undefined +>u?.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>u : U2 +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>key2 : string | number | undefined >'number' : "number" u; // U2 ->u : U1 +>u : U2 + + u.key1.key2; +>u.key1.key2 : string +>u.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>u : U2 +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>key2 : string } if (typeof u?.key1?.key2 === 'number') { >typeof u?.key1?.key2 === 'number' : boolean >typeof u?.key1?.key2 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" ->u?.key1?.key2 : string | number ->u?.key1 : { key2: number; } | { key2: string; } | { key2: number; } ->u : U1 ->key1 : { key2: number; } | { key2: string; } | { key2: number; } ->key2 : string | number +>u?.key1?.key2 : string | number | undefined +>u?.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>u : U2 +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>key2 : string | number | undefined >'number' : "number" u; // Foo1 | Foo3 >u : Foo1 | Foo3 + + u.key1.key2; +>u.key1.key2 : number +>u.key1 : { key2: number; } | { key2: number; } +>u : Foo1 | Foo3 +>key1 : { key2: number; } | { key2: number; } +>key2 : number } if (typeof u?.key1?.key2 !== 'undefined') { >typeof u?.key1?.key2 !== 'undefined' : boolean >typeof u?.key1?.key2 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" ->u?.key1?.key2 : string | number ->u?.key1 : { key2: number; } | { key2: string; } | { key2: number; } ->u : U1 ->key1 : { key2: number; } | { key2: string; } | { key2: number; } ->key2 : string | number +>u?.key1?.key2 : string | number | undefined +>u?.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>u : U2 +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>key2 : string | number | undefined >'undefined' : "undefined" u; // Foo1 | Foo2 | Foo3 >u : U1 + + u.key1.key2; +>u.key1.key2 : string | number +>u.key1 : { key2: number; } | { key2: string; } | { key2: number; } +>u : U1 +>key1 : { key2: number; } | { key2: string; } | { key2: number; } +>key2 : string | number } if (typeof u?.key1?.key2 === 'undefined') { >typeof u?.key1?.key2 === 'undefined' : boolean >typeof u?.key1?.key2 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" ->u?.key1?.key2 : string | number ->u?.key1 : { key2: number; } | { key2: string; } | { key2: number; } ->u : U1 ->key1 : { key2: number; } | { key2: string; } | { key2: number; } ->key2 : string | number +>u?.key1?.key2 : string | number | undefined +>u?.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>u : U2 +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>key2 : string | number | undefined >'undefined' : "undefined" u; // U2 ->u : U1 +>u : U2 + + u.key1.key2; +>u.key1.key2 : never +>u.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>u : U2 +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>key2 : never } } diff --git a/tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToProperty.ts b/tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToProperty.ts index 06695b5d87137..f9d11f2b1a559 100644 --- a/tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToProperty.ts +++ b/tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToProperty.ts @@ -1,4 +1,4 @@ -// @strictNullChecks: true +// @strict: true // Primitive value ---- boolean bigint number string symbol undefined function object // ts special type ---- any, void, unknown, union, intersection diff --git a/tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToPropertyBySwitch.ts b/tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToPropertyBySwitch.ts index 28125a553e4d8..db96b970f7c02 100644 --- a/tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToPropertyBySwitch.ts +++ b/tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToPropertyBySwitch.ts @@ -1,3 +1,4 @@ +// @strict: true interface Foo1 { firstKey: number, diff --git a/tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToPropertyDeep.ts b/tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToPropertyDeep.ts index b5f6ec60914dd..9de6fcb552669 100644 --- a/tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToPropertyDeep.ts +++ b/tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToPropertyDeep.ts @@ -1,4 +1,4 @@ -// @strictNullChecks: true +// @strict: true //// deep property access ---- a.b.c.d.e.f, a["b"]["c"]["d"] //// mix deep property access ---- a.b["c"]["d"].e diff --git a/tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToPropertyOptional.ts b/tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToPropertyOptional.ts index d02ed8dc86084..d3211e253a787 100644 --- a/tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToPropertyOptional.ts +++ b/tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToPropertyOptional.ts @@ -1,3 +1,5 @@ +// @strict: true + interface Foo1 { key1:{ key2:number; @@ -81,29 +83,37 @@ function f2Plus(u: U1){ function f3(u: U2) { if (typeof u?.key1 !== 'number') { u; // U2 + u.key1.key2; } if (typeof u?.key1 === 'number') { u; // never + u.key1.key2; } if (typeof u?.key1 !== 'undefined') { u; // Foo1 | Foo2 | Foo3 + u.key1.key2; } if (typeof u?.key1 === 'undefined') { u; // U2 + u.key1.key2; } } function f4(u: U2) { if (typeof u?.key1?.key2 !== 'number') { u; // U2 + u.key1.key2; } if (typeof u?.key1?.key2 === 'number') { u; // Foo1 | Foo3 + u.key1.key2; } if (typeof u?.key1?.key2 !== 'undefined') { u; // Foo1 | Foo2 | Foo3 + u.key1.key2; } if (typeof u?.key1?.key2 === 'undefined') { u; // U2 + u.key1.key2; } }