mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Narrow via discriminant property through optional chain (#42450)
* Naive attempt at narrowing via discriminant property through optional chain * Clean up test
This commit is contained in:
@@ -22599,10 +22599,13 @@ namespace ts {
|
||||
if (propName === undefined) {
|
||||
return type;
|
||||
}
|
||||
const propType = getTypeOfPropertyOfType(type, propName);
|
||||
const includesUndefined = strictNullChecks && maybeTypeOfKind(type, TypeFlags.Undefined);
|
||||
const removeOptional = includesUndefined && isOptionalChain(access);
|
||||
let propType = getTypeOfPropertyOfType(removeOptional ? getTypeWithFacts(type, TypeFacts.NEUndefined) : type, propName);
|
||||
if (!propType) {
|
||||
return type;
|
||||
}
|
||||
propType = removeOptional ? getOptionalType(propType) : propType;
|
||||
const narrowedPropType = narrowType(propType);
|
||||
return filterType(type, t => {
|
||||
const discriminantType = getTypeOfPropertyOrIndexSignature(t, propName);
|
||||
|
||||
@@ -200,14 +200,14 @@ else {
|
||||
>o3 : Symbol(o3, Decl(controlFlowOptionalChain.ts, 58, 13))
|
||||
|
||||
o3?.x;
|
||||
>o3?.x : Symbol(x, Decl(controlFlowOptionalChain.ts, 58, 19), Decl(controlFlowOptionalChain.ts, 58, 41))
|
||||
>o3?.x : Symbol(x, Decl(controlFlowOptionalChain.ts, 58, 41))
|
||||
>o3 : Symbol(o3, Decl(controlFlowOptionalChain.ts, 58, 13))
|
||||
>x : Symbol(x, Decl(controlFlowOptionalChain.ts, 58, 19), Decl(controlFlowOptionalChain.ts, 58, 41))
|
||||
>x : Symbol(x, Decl(controlFlowOptionalChain.ts, 58, 41))
|
||||
|
||||
o3.x;
|
||||
>o3.x : Symbol(x, Decl(controlFlowOptionalChain.ts, 58, 19), Decl(controlFlowOptionalChain.ts, 58, 41))
|
||||
>o3.x : Symbol(x, Decl(controlFlowOptionalChain.ts, 58, 41))
|
||||
>o3 : Symbol(o3, Decl(controlFlowOptionalChain.ts, 58, 13))
|
||||
>x : Symbol(x, Decl(controlFlowOptionalChain.ts, 58, 19), Decl(controlFlowOptionalChain.ts, 58, 41))
|
||||
>x : Symbol(x, Decl(controlFlowOptionalChain.ts, 58, 41))
|
||||
}
|
||||
o3;
|
||||
>o3 : Symbol(o3, Decl(controlFlowOptionalChain.ts, 58, 13))
|
||||
|
||||
@@ -223,16 +223,16 @@ if (o3?.x === 1) {
|
||||
}
|
||||
else {
|
||||
o3;
|
||||
>o3 : { x: 1; y: string; } | { x: 2; y: number; } | undefined
|
||||
>o3 : { x: 2; y: number; } | undefined
|
||||
|
||||
o3?.x;
|
||||
>o3?.x : 2 | undefined
|
||||
>o3 : { x: 1; y: string; } | { x: 2; y: number; } | undefined
|
||||
>o3 : { x: 2; y: number; } | undefined
|
||||
>x : 2 | undefined
|
||||
|
||||
o3.x;
|
||||
>o3.x : 2
|
||||
>o3 : { x: 1; y: string; } | { x: 2; y: number; } | undefined
|
||||
>o3 : { x: 2; y: number; } | undefined
|
||||
>x : 2
|
||||
}
|
||||
o3;
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
//// [controlFlowOptionalChain2.ts]
|
||||
type A = {
|
||||
type: 'A';
|
||||
name: string;
|
||||
}
|
||||
|
||||
type B = {
|
||||
type: 'B';
|
||||
}
|
||||
|
||||
function funcTwo(arg: A | B | undefined) {
|
||||
if (arg?.type === 'B') {
|
||||
arg; // `B`
|
||||
return;
|
||||
}
|
||||
|
||||
arg;
|
||||
arg?.name;
|
||||
}
|
||||
|
||||
|
||||
//// [controlFlowOptionalChain2.js]
|
||||
function funcTwo(arg) {
|
||||
if ((arg === null || arg === void 0 ? void 0 : arg.type) === 'B') {
|
||||
arg; // `B`
|
||||
return;
|
||||
}
|
||||
arg;
|
||||
arg === null || arg === void 0 ? void 0 : arg.name;
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
=== tests/cases/conformance/controlFlow/controlFlowOptionalChain2.ts ===
|
||||
type A = {
|
||||
>A : Symbol(A, Decl(controlFlowOptionalChain2.ts, 0, 0))
|
||||
|
||||
type: 'A';
|
||||
>type : Symbol(type, Decl(controlFlowOptionalChain2.ts, 0, 10))
|
||||
|
||||
name: string;
|
||||
>name : Symbol(name, Decl(controlFlowOptionalChain2.ts, 1, 12))
|
||||
}
|
||||
|
||||
type B = {
|
||||
>B : Symbol(B, Decl(controlFlowOptionalChain2.ts, 3, 1))
|
||||
|
||||
type: 'B';
|
||||
>type : Symbol(type, Decl(controlFlowOptionalChain2.ts, 5, 10))
|
||||
}
|
||||
|
||||
function funcTwo(arg: A | B | undefined) {
|
||||
>funcTwo : Symbol(funcTwo, Decl(controlFlowOptionalChain2.ts, 7, 1))
|
||||
>arg : Symbol(arg, Decl(controlFlowOptionalChain2.ts, 9, 17))
|
||||
>A : Symbol(A, Decl(controlFlowOptionalChain2.ts, 0, 0))
|
||||
>B : Symbol(B, Decl(controlFlowOptionalChain2.ts, 3, 1))
|
||||
|
||||
if (arg?.type === 'B') {
|
||||
>arg?.type : Symbol(type, Decl(controlFlowOptionalChain2.ts, 0, 10), Decl(controlFlowOptionalChain2.ts, 5, 10))
|
||||
>arg : Symbol(arg, Decl(controlFlowOptionalChain2.ts, 9, 17))
|
||||
>type : Symbol(type, Decl(controlFlowOptionalChain2.ts, 0, 10), Decl(controlFlowOptionalChain2.ts, 5, 10))
|
||||
|
||||
arg; // `B`
|
||||
>arg : Symbol(arg, Decl(controlFlowOptionalChain2.ts, 9, 17))
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
arg;
|
||||
>arg : Symbol(arg, Decl(controlFlowOptionalChain2.ts, 9, 17))
|
||||
|
||||
arg?.name;
|
||||
>arg?.name : Symbol(name, Decl(controlFlowOptionalChain2.ts, 1, 12))
|
||||
>arg : Symbol(arg, Decl(controlFlowOptionalChain2.ts, 9, 17))
|
||||
>name : Symbol(name, Decl(controlFlowOptionalChain2.ts, 1, 12))
|
||||
}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
=== tests/cases/conformance/controlFlow/controlFlowOptionalChain2.ts ===
|
||||
type A = {
|
||||
>A : A
|
||||
|
||||
type: 'A';
|
||||
>type : "A"
|
||||
|
||||
name: string;
|
||||
>name : string
|
||||
}
|
||||
|
||||
type B = {
|
||||
>B : B
|
||||
|
||||
type: 'B';
|
||||
>type : "B"
|
||||
}
|
||||
|
||||
function funcTwo(arg: A | B | undefined) {
|
||||
>funcTwo : (arg: A | B | undefined) => void
|
||||
>arg : A | B | undefined
|
||||
|
||||
if (arg?.type === 'B') {
|
||||
>arg?.type === 'B' : boolean
|
||||
>arg?.type : "A" | "B" | undefined
|
||||
>arg : A | B | undefined
|
||||
>type : "A" | "B" | undefined
|
||||
>'B' : "B"
|
||||
|
||||
arg; // `B`
|
||||
>arg : B
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
arg;
|
||||
>arg : A | undefined
|
||||
|
||||
arg?.name;
|
||||
>arg?.name : string | undefined
|
||||
>arg : A | undefined
|
||||
>name : string | undefined
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
// @strictNullChecks: true
|
||||
|
||||
type A = {
|
||||
type: 'A';
|
||||
name: string;
|
||||
}
|
||||
|
||||
type B = {
|
||||
type: 'B';
|
||||
}
|
||||
|
||||
function funcTwo(arg: A | B | undefined) {
|
||||
if (arg?.type === 'B') {
|
||||
arg; // `B`
|
||||
return;
|
||||
}
|
||||
|
||||
arg;
|
||||
arg?.name;
|
||||
}
|
||||
Reference in New Issue
Block a user