Fix check in getDiscriminantPropertyAccess (#55464)

This commit is contained in:
Anders Hejlsberg 2023-08-23 11:43:41 -07:00 committed by GitHub
parent 6d07d5fa40
commit fcaa900012
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 166 additions and 1 deletions

View File

@ -27460,7 +27460,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}
function getDiscriminantPropertyAccess(expr: Expression, computedType: Type) {
const type = declaredType.flags & TypeFlags.Union ? declaredType : computedType;
const type = !(computedType.flags & TypeFlags.Union) && declaredType.flags & TypeFlags.Union ? declaredType : computedType;
if (type.flags & TypeFlags.Union) {
const access = getCandidateDiscriminantPropertyAccess(expr);
if (access) {

View File

@ -212,6 +212,20 @@ function f1x(obj: (string | number)[] | null) {
assertRelationIsNullOrStringArray(obj);
obj; // string[] | null
}
// Repro from #55425
type MyDiscriminatedUnion = { type: 'A', aProp: number } | { type: 'B', bProp: string };
declare function isMyDiscriminatedUnion(item: unknown): item is MyDiscriminatedUnion;
declare const working: unknown;
declare const broken: Record<string, any> | undefined;
declare const workingAgain: Record<string, any> | undefined | unknown;
isMyDiscriminatedUnion(working) && working.type === 'A' && working.aProp;
isMyDiscriminatedUnion(broken) && broken.type === 'A' && broken.aProp;
isMyDiscriminatedUnion(workingAgain) && workingAgain.type === 'A' && workingAgain.aProp;
//// [narrowingUnionToUnion.js]
@ -370,6 +384,9 @@ function f1x(obj) {
assertRelationIsNullOrStringArray(obj);
obj; // string[] | null
}
isMyDiscriminatedUnion(working) && working.type === 'A' && working.aProp;
isMyDiscriminatedUnion(broken) && broken.type === 'A' && broken.aProp;
isMyDiscriminatedUnion(workingAgain) && workingAgain.type === 'A' && workingAgain.aProp;
//// [narrowingUnionToUnion.d.ts]
@ -423,3 +440,14 @@ declare function check2(x: unknown): x is ("hello" | 0);
declare function test3(x: unknown): void;
declare function assertRelationIsNullOrStringArray(v: (string | number)[] | null): asserts v is string[] | null;
declare function f1x(obj: (string | number)[] | null): void;
type MyDiscriminatedUnion = {
type: 'A';
aProp: number;
} | {
type: 'B';
bProp: string;
};
declare function isMyDiscriminatedUnion(item: unknown): item is MyDiscriminatedUnion;
declare const working: unknown;
declare const broken: Record<string, any> | undefined;
declare const workingAgain: Record<string, any> | undefined | unknown;

View File

@ -482,3 +482,59 @@ function f1x(obj: (string | number)[] | null) {
>obj : Symbol(obj, Decl(narrowingUnionToUnion.ts, 207, 13))
}
// Repro from #55425
type MyDiscriminatedUnion = { type: 'A', aProp: number } | { type: 'B', bProp: string };
>MyDiscriminatedUnion : Symbol(MyDiscriminatedUnion, Decl(narrowingUnionToUnion.ts, 210, 1))
>type : Symbol(type, Decl(narrowingUnionToUnion.ts, 214, 29))
>aProp : Symbol(aProp, Decl(narrowingUnionToUnion.ts, 214, 40))
>type : Symbol(type, Decl(narrowingUnionToUnion.ts, 214, 60))
>bProp : Symbol(bProp, Decl(narrowingUnionToUnion.ts, 214, 71))
declare function isMyDiscriminatedUnion(item: unknown): item is MyDiscriminatedUnion;
>isMyDiscriminatedUnion : Symbol(isMyDiscriminatedUnion, Decl(narrowingUnionToUnion.ts, 214, 88))
>item : Symbol(item, Decl(narrowingUnionToUnion.ts, 216, 40))
>item : Symbol(item, Decl(narrowingUnionToUnion.ts, 216, 40))
>MyDiscriminatedUnion : Symbol(MyDiscriminatedUnion, Decl(narrowingUnionToUnion.ts, 210, 1))
declare const working: unknown;
>working : Symbol(working, Decl(narrowingUnionToUnion.ts, 218, 13))
declare const broken: Record<string, any> | undefined;
>broken : Symbol(broken, Decl(narrowingUnionToUnion.ts, 219, 13))
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
declare const workingAgain: Record<string, any> | undefined | unknown;
>workingAgain : Symbol(workingAgain, Decl(narrowingUnionToUnion.ts, 220, 13))
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
isMyDiscriminatedUnion(working) && working.type === 'A' && working.aProp;
>isMyDiscriminatedUnion : Symbol(isMyDiscriminatedUnion, Decl(narrowingUnionToUnion.ts, 214, 88))
>working : Symbol(working, Decl(narrowingUnionToUnion.ts, 218, 13))
>working.type : Symbol(type, Decl(narrowingUnionToUnion.ts, 214, 29), Decl(narrowingUnionToUnion.ts, 214, 60))
>working : Symbol(working, Decl(narrowingUnionToUnion.ts, 218, 13))
>type : Symbol(type, Decl(narrowingUnionToUnion.ts, 214, 29), Decl(narrowingUnionToUnion.ts, 214, 60))
>working.aProp : Symbol(aProp, Decl(narrowingUnionToUnion.ts, 214, 40))
>working : Symbol(working, Decl(narrowingUnionToUnion.ts, 218, 13))
>aProp : Symbol(aProp, Decl(narrowingUnionToUnion.ts, 214, 40))
isMyDiscriminatedUnion(broken) && broken.type === 'A' && broken.aProp;
>isMyDiscriminatedUnion : Symbol(isMyDiscriminatedUnion, Decl(narrowingUnionToUnion.ts, 214, 88))
>broken : Symbol(broken, Decl(narrowingUnionToUnion.ts, 219, 13))
>broken.type : Symbol(type, Decl(narrowingUnionToUnion.ts, 214, 29), Decl(narrowingUnionToUnion.ts, 214, 60))
>broken : Symbol(broken, Decl(narrowingUnionToUnion.ts, 219, 13))
>type : Symbol(type, Decl(narrowingUnionToUnion.ts, 214, 29), Decl(narrowingUnionToUnion.ts, 214, 60))
>broken.aProp : Symbol(aProp, Decl(narrowingUnionToUnion.ts, 214, 40))
>broken : Symbol(broken, Decl(narrowingUnionToUnion.ts, 219, 13))
>aProp : Symbol(aProp, Decl(narrowingUnionToUnion.ts, 214, 40))
isMyDiscriminatedUnion(workingAgain) && workingAgain.type === 'A' && workingAgain.aProp;
>isMyDiscriminatedUnion : Symbol(isMyDiscriminatedUnion, Decl(narrowingUnionToUnion.ts, 214, 88))
>workingAgain : Symbol(workingAgain, Decl(narrowingUnionToUnion.ts, 220, 13))
>workingAgain.type : Symbol(type, Decl(narrowingUnionToUnion.ts, 214, 29), Decl(narrowingUnionToUnion.ts, 214, 60))
>workingAgain : Symbol(workingAgain, Decl(narrowingUnionToUnion.ts, 220, 13))
>type : Symbol(type, Decl(narrowingUnionToUnion.ts, 214, 29), Decl(narrowingUnionToUnion.ts, 214, 60))
>workingAgain.aProp : Symbol(aProp, Decl(narrowingUnionToUnion.ts, 214, 40))
>workingAgain : Symbol(workingAgain, Decl(narrowingUnionToUnion.ts, 220, 13))
>aProp : Symbol(aProp, Decl(narrowingUnionToUnion.ts, 214, 40))

View File

@ -507,3 +507,70 @@ function f1x(obj: (string | number)[] | null) {
>obj : string[] | null
}
// Repro from #55425
type MyDiscriminatedUnion = { type: 'A', aProp: number } | { type: 'B', bProp: string };
>MyDiscriminatedUnion : { type: 'A'; aProp: number; } | { type: 'B'; bProp: string; }
>type : "A"
>aProp : number
>type : "B"
>bProp : string
declare function isMyDiscriminatedUnion(item: unknown): item is MyDiscriminatedUnion;
>isMyDiscriminatedUnion : (item: unknown) => item is MyDiscriminatedUnion
>item : unknown
declare const working: unknown;
>working : unknown
declare const broken: Record<string, any> | undefined;
>broken : Record<string, any> | undefined
declare const workingAgain: Record<string, any> | undefined | unknown;
>workingAgain : unknown
isMyDiscriminatedUnion(working) && working.type === 'A' && working.aProp;
>isMyDiscriminatedUnion(working) && working.type === 'A' && working.aProp : number | false
>isMyDiscriminatedUnion(working) && working.type === 'A' : boolean
>isMyDiscriminatedUnion(working) : boolean
>isMyDiscriminatedUnion : (item: unknown) => item is MyDiscriminatedUnion
>working : unknown
>working.type === 'A' : boolean
>working.type : "A" | "B"
>working : MyDiscriminatedUnion
>type : "A" | "B"
>'A' : "A"
>working.aProp : number
>working : { type: "A"; aProp: number; }
>aProp : number
isMyDiscriminatedUnion(broken) && broken.type === 'A' && broken.aProp;
>isMyDiscriminatedUnion(broken) && broken.type === 'A' && broken.aProp : number | false
>isMyDiscriminatedUnion(broken) && broken.type === 'A' : boolean
>isMyDiscriminatedUnion(broken) : boolean
>isMyDiscriminatedUnion : (item: unknown) => item is MyDiscriminatedUnion
>broken : Record<string, any> | undefined
>broken.type === 'A' : boolean
>broken.type : "A" | "B"
>broken : MyDiscriminatedUnion
>type : "A" | "B"
>'A' : "A"
>broken.aProp : number
>broken : { type: "A"; aProp: number; }
>aProp : number
isMyDiscriminatedUnion(workingAgain) && workingAgain.type === 'A' && workingAgain.aProp;
>isMyDiscriminatedUnion(workingAgain) && workingAgain.type === 'A' && workingAgain.aProp : number | false
>isMyDiscriminatedUnion(workingAgain) && workingAgain.type === 'A' : boolean
>isMyDiscriminatedUnion(workingAgain) : boolean
>isMyDiscriminatedUnion : (item: unknown) => item is MyDiscriminatedUnion
>workingAgain : unknown
>workingAgain.type === 'A' : boolean
>workingAgain.type : "A" | "B"
>workingAgain : MyDiscriminatedUnion
>type : "A" | "B"
>'A' : "A"
>workingAgain.aProp : number
>workingAgain : { type: "A"; aProp: number; }
>aProp : number

View File

@ -212,3 +212,17 @@ function f1x(obj: (string | number)[] | null) {
assertRelationIsNullOrStringArray(obj);
obj; // string[] | null
}
// Repro from #55425
type MyDiscriminatedUnion = { type: 'A', aProp: number } | { type: 'B', bProp: string };
declare function isMyDiscriminatedUnion(item: unknown): item is MyDiscriminatedUnion;
declare const working: unknown;
declare const broken: Record<string, any> | undefined;
declare const workingAgain: Record<string, any> | undefined | unknown;
isMyDiscriminatedUnion(working) && working.type === 'A' && working.aProp;
isMyDiscriminatedUnion(broken) && broken.type === 'A' && broken.aProp;
isMyDiscriminatedUnion(workingAgain) && workingAgain.type === 'A' && workingAgain.aProp;