Skip to content

Commit fcaa900

Browse files
authored
Fix check in getDiscriminantPropertyAccess (#55464)
1 parent 6d07d5f commit fcaa900

File tree

5 files changed

+166
-1
lines changed

5 files changed

+166
-1
lines changed

src/compiler/checker.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27460,7 +27460,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2746027460
}
2746127461

2746227462
function getDiscriminantPropertyAccess(expr: Expression, computedType: Type) {
27463-
const type = declaredType.flags & TypeFlags.Union ? declaredType : computedType;
27463+
const type = !(computedType.flags & TypeFlags.Union) && declaredType.flags & TypeFlags.Union ? declaredType : computedType;
2746427464
if (type.flags & TypeFlags.Union) {
2746527465
const access = getCandidateDiscriminantPropertyAccess(expr);
2746627466
if (access) {

tests/baselines/reference/narrowingUnionToUnion.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,20 @@ function f1x(obj: (string | number)[] | null) {
212212
assertRelationIsNullOrStringArray(obj);
213213
obj; // string[] | null
214214
}
215+
216+
// Repro from #55425
217+
218+
type MyDiscriminatedUnion = { type: 'A', aProp: number } | { type: 'B', bProp: string };
219+
220+
declare function isMyDiscriminatedUnion(item: unknown): item is MyDiscriminatedUnion;
221+
222+
declare const working: unknown;
223+
declare const broken: Record<string, any> | undefined;
224+
declare const workingAgain: Record<string, any> | undefined | unknown;
225+
226+
isMyDiscriminatedUnion(working) && working.type === 'A' && working.aProp;
227+
isMyDiscriminatedUnion(broken) && broken.type === 'A' && broken.aProp;
228+
isMyDiscriminatedUnion(workingAgain) && workingAgain.type === 'A' && workingAgain.aProp;
215229

216230

217231
//// [narrowingUnionToUnion.js]
@@ -370,6 +384,9 @@ function f1x(obj) {
370384
assertRelationIsNullOrStringArray(obj);
371385
obj; // string[] | null
372386
}
387+
isMyDiscriminatedUnion(working) && working.type === 'A' && working.aProp;
388+
isMyDiscriminatedUnion(broken) && broken.type === 'A' && broken.aProp;
389+
isMyDiscriminatedUnion(workingAgain) && workingAgain.type === 'A' && workingAgain.aProp;
373390

374391

375392
//// [narrowingUnionToUnion.d.ts]
@@ -423,3 +440,14 @@ declare function check2(x: unknown): x is ("hello" | 0);
423440
declare function test3(x: unknown): void;
424441
declare function assertRelationIsNullOrStringArray(v: (string | number)[] | null): asserts v is string[] | null;
425442
declare function f1x(obj: (string | number)[] | null): void;
443+
type MyDiscriminatedUnion = {
444+
type: 'A';
445+
aProp: number;
446+
} | {
447+
type: 'B';
448+
bProp: string;
449+
};
450+
declare function isMyDiscriminatedUnion(item: unknown): item is MyDiscriminatedUnion;
451+
declare const working: unknown;
452+
declare const broken: Record<string, any> | undefined;
453+
declare const workingAgain: Record<string, any> | undefined | unknown;

tests/baselines/reference/narrowingUnionToUnion.symbols

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -482,3 +482,59 @@ function f1x(obj: (string | number)[] | null) {
482482
>obj : Symbol(obj, Decl(narrowingUnionToUnion.ts, 207, 13))
483483
}
484484

485+
// Repro from #55425
486+
487+
type MyDiscriminatedUnion = { type: 'A', aProp: number } | { type: 'B', bProp: string };
488+
>MyDiscriminatedUnion : Symbol(MyDiscriminatedUnion, Decl(narrowingUnionToUnion.ts, 210, 1))
489+
>type : Symbol(type, Decl(narrowingUnionToUnion.ts, 214, 29))
490+
>aProp : Symbol(aProp, Decl(narrowingUnionToUnion.ts, 214, 40))
491+
>type : Symbol(type, Decl(narrowingUnionToUnion.ts, 214, 60))
492+
>bProp : Symbol(bProp, Decl(narrowingUnionToUnion.ts, 214, 71))
493+
494+
declare function isMyDiscriminatedUnion(item: unknown): item is MyDiscriminatedUnion;
495+
>isMyDiscriminatedUnion : Symbol(isMyDiscriminatedUnion, Decl(narrowingUnionToUnion.ts, 214, 88))
496+
>item : Symbol(item, Decl(narrowingUnionToUnion.ts, 216, 40))
497+
>item : Symbol(item, Decl(narrowingUnionToUnion.ts, 216, 40))
498+
>MyDiscriminatedUnion : Symbol(MyDiscriminatedUnion, Decl(narrowingUnionToUnion.ts, 210, 1))
499+
500+
declare const working: unknown;
501+
>working : Symbol(working, Decl(narrowingUnionToUnion.ts, 218, 13))
502+
503+
declare const broken: Record<string, any> | undefined;
504+
>broken : Symbol(broken, Decl(narrowingUnionToUnion.ts, 219, 13))
505+
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
506+
507+
declare const workingAgain: Record<string, any> | undefined | unknown;
508+
>workingAgain : Symbol(workingAgain, Decl(narrowingUnionToUnion.ts, 220, 13))
509+
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
510+
511+
isMyDiscriminatedUnion(working) && working.type === 'A' && working.aProp;
512+
>isMyDiscriminatedUnion : Symbol(isMyDiscriminatedUnion, Decl(narrowingUnionToUnion.ts, 214, 88))
513+
>working : Symbol(working, Decl(narrowingUnionToUnion.ts, 218, 13))
514+
>working.type : Symbol(type, Decl(narrowingUnionToUnion.ts, 214, 29), Decl(narrowingUnionToUnion.ts, 214, 60))
515+
>working : Symbol(working, Decl(narrowingUnionToUnion.ts, 218, 13))
516+
>type : Symbol(type, Decl(narrowingUnionToUnion.ts, 214, 29), Decl(narrowingUnionToUnion.ts, 214, 60))
517+
>working.aProp : Symbol(aProp, Decl(narrowingUnionToUnion.ts, 214, 40))
518+
>working : Symbol(working, Decl(narrowingUnionToUnion.ts, 218, 13))
519+
>aProp : Symbol(aProp, Decl(narrowingUnionToUnion.ts, 214, 40))
520+
521+
isMyDiscriminatedUnion(broken) && broken.type === 'A' && broken.aProp;
522+
>isMyDiscriminatedUnion : Symbol(isMyDiscriminatedUnion, Decl(narrowingUnionToUnion.ts, 214, 88))
523+
>broken : Symbol(broken, Decl(narrowingUnionToUnion.ts, 219, 13))
524+
>broken.type : Symbol(type, Decl(narrowingUnionToUnion.ts, 214, 29), Decl(narrowingUnionToUnion.ts, 214, 60))
525+
>broken : Symbol(broken, Decl(narrowingUnionToUnion.ts, 219, 13))
526+
>type : Symbol(type, Decl(narrowingUnionToUnion.ts, 214, 29), Decl(narrowingUnionToUnion.ts, 214, 60))
527+
>broken.aProp : Symbol(aProp, Decl(narrowingUnionToUnion.ts, 214, 40))
528+
>broken : Symbol(broken, Decl(narrowingUnionToUnion.ts, 219, 13))
529+
>aProp : Symbol(aProp, Decl(narrowingUnionToUnion.ts, 214, 40))
530+
531+
isMyDiscriminatedUnion(workingAgain) && workingAgain.type === 'A' && workingAgain.aProp;
532+
>isMyDiscriminatedUnion : Symbol(isMyDiscriminatedUnion, Decl(narrowingUnionToUnion.ts, 214, 88))
533+
>workingAgain : Symbol(workingAgain, Decl(narrowingUnionToUnion.ts, 220, 13))
534+
>workingAgain.type : Symbol(type, Decl(narrowingUnionToUnion.ts, 214, 29), Decl(narrowingUnionToUnion.ts, 214, 60))
535+
>workingAgain : Symbol(workingAgain, Decl(narrowingUnionToUnion.ts, 220, 13))
536+
>type : Symbol(type, Decl(narrowingUnionToUnion.ts, 214, 29), Decl(narrowingUnionToUnion.ts, 214, 60))
537+
>workingAgain.aProp : Symbol(aProp, Decl(narrowingUnionToUnion.ts, 214, 40))
538+
>workingAgain : Symbol(workingAgain, Decl(narrowingUnionToUnion.ts, 220, 13))
539+
>aProp : Symbol(aProp, Decl(narrowingUnionToUnion.ts, 214, 40))
540+

tests/baselines/reference/narrowingUnionToUnion.types

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,3 +507,70 @@ function f1x(obj: (string | number)[] | null) {
507507
>obj : string[] | null
508508
}
509509

510+
// Repro from #55425
511+
512+
type MyDiscriminatedUnion = { type: 'A', aProp: number } | { type: 'B', bProp: string };
513+
>MyDiscriminatedUnion : { type: 'A'; aProp: number; } | { type: 'B'; bProp: string; }
514+
>type : "A"
515+
>aProp : number
516+
>type : "B"
517+
>bProp : string
518+
519+
declare function isMyDiscriminatedUnion(item: unknown): item is MyDiscriminatedUnion;
520+
>isMyDiscriminatedUnion : (item: unknown) => item is MyDiscriminatedUnion
521+
>item : unknown
522+
523+
declare const working: unknown;
524+
>working : unknown
525+
526+
declare const broken: Record<string, any> | undefined;
527+
>broken : Record<string, any> | undefined
528+
529+
declare const workingAgain: Record<string, any> | undefined | unknown;
530+
>workingAgain : unknown
531+
532+
isMyDiscriminatedUnion(working) && working.type === 'A' && working.aProp;
533+
>isMyDiscriminatedUnion(working) && working.type === 'A' && working.aProp : number | false
534+
>isMyDiscriminatedUnion(working) && working.type === 'A' : boolean
535+
>isMyDiscriminatedUnion(working) : boolean
536+
>isMyDiscriminatedUnion : (item: unknown) => item is MyDiscriminatedUnion
537+
>working : unknown
538+
>working.type === 'A' : boolean
539+
>working.type : "A" | "B"
540+
>working : MyDiscriminatedUnion
541+
>type : "A" | "B"
542+
>'A' : "A"
543+
>working.aProp : number
544+
>working : { type: "A"; aProp: number; }
545+
>aProp : number
546+
547+
isMyDiscriminatedUnion(broken) && broken.type === 'A' && broken.aProp;
548+
>isMyDiscriminatedUnion(broken) && broken.type === 'A' && broken.aProp : number | false
549+
>isMyDiscriminatedUnion(broken) && broken.type === 'A' : boolean
550+
>isMyDiscriminatedUnion(broken) : boolean
551+
>isMyDiscriminatedUnion : (item: unknown) => item is MyDiscriminatedUnion
552+
>broken : Record<string, any> | undefined
553+
>broken.type === 'A' : boolean
554+
>broken.type : "A" | "B"
555+
>broken : MyDiscriminatedUnion
556+
>type : "A" | "B"
557+
>'A' : "A"
558+
>broken.aProp : number
559+
>broken : { type: "A"; aProp: number; }
560+
>aProp : number
561+
562+
isMyDiscriminatedUnion(workingAgain) && workingAgain.type === 'A' && workingAgain.aProp;
563+
>isMyDiscriminatedUnion(workingAgain) && workingAgain.type === 'A' && workingAgain.aProp : number | false
564+
>isMyDiscriminatedUnion(workingAgain) && workingAgain.type === 'A' : boolean
565+
>isMyDiscriminatedUnion(workingAgain) : boolean
566+
>isMyDiscriminatedUnion : (item: unknown) => item is MyDiscriminatedUnion
567+
>workingAgain : unknown
568+
>workingAgain.type === 'A' : boolean
569+
>workingAgain.type : "A" | "B"
570+
>workingAgain : MyDiscriminatedUnion
571+
>type : "A" | "B"
572+
>'A' : "A"
573+
>workingAgain.aProp : number
574+
>workingAgain : { type: "A"; aProp: number; }
575+
>aProp : number
576+

tests/cases/compiler/narrowingUnionToUnion.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,3 +212,17 @@ function f1x(obj: (string | number)[] | null) {
212212
assertRelationIsNullOrStringArray(obj);
213213
obj; // string[] | null
214214
}
215+
216+
// Repro from #55425
217+
218+
type MyDiscriminatedUnion = { type: 'A', aProp: number } | { type: 'B', bProp: string };
219+
220+
declare function isMyDiscriminatedUnion(item: unknown): item is MyDiscriminatedUnion;
221+
222+
declare const working: unknown;
223+
declare const broken: Record<string, any> | undefined;
224+
declare const workingAgain: Record<string, any> | undefined | unknown;
225+
226+
isMyDiscriminatedUnion(working) && working.type === 'A' && working.aProp;
227+
isMyDiscriminatedUnion(broken) && broken.type === 'A' && broken.aProp;
228+
isMyDiscriminatedUnion(workingAgain) && workingAgain.type === 'A' && workingAgain.aProp;

0 commit comments

Comments
 (0)