Skip to content

Commit a8e13f7

Browse files
authoredSep 17, 2022
Fixed an issue with destructured bindings from a generic union constraint not being narrowed correctly (#50221)
1 parent 08af0b6 commit a8e13f7

6 files changed

+523
-322
lines changed
 

‎src/compiler/checker.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -25924,10 +25924,11 @@ namespace ts {
2592425924
if (!(links.flags & NodeCheckFlags.InCheckIdentifier)) {
2592525925
links.flags |= NodeCheckFlags.InCheckIdentifier;
2592625926
const parentType = getTypeForBindingElementParent(parent, CheckMode.Normal);
25927+
const parentTypeConstraint = parentType && mapType(parentType, getBaseConstraintOrType);
2592725928
links.flags &= ~NodeCheckFlags.InCheckIdentifier;
25928-
if (parentType && parentType.flags & TypeFlags.Union && !(parent.kind === SyntaxKind.Parameter && isSymbolAssigned(symbol))) {
25929+
if (parentTypeConstraint && parentTypeConstraint.flags & TypeFlags.Union && !(parent.kind === SyntaxKind.Parameter && isSymbolAssigned(symbol))) {
2592925930
const pattern = declaration.parent;
25930-
const narrowedType = getFlowTypeOfReference(pattern, parentType, parentType, /*flowContainer*/ undefined, location.flowNode);
25931+
const narrowedType = getFlowTypeOfReference(pattern, parentTypeConstraint, parentTypeConstraint, /*flowContainer*/ undefined, location.flowNode);
2593125932
if (narrowedType.flags & TypeFlags.Never) {
2593225933
return neverType;
2593325934
}

‎tests/baselines/reference/dependentDestructuredVariables.errors.txt

+22-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
tests/cases/conformance/controlFlow/dependentDestructuredVariables.ts(314,5): error TS7022: 'value1' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer.
2-
tests/cases/conformance/controlFlow/dependentDestructuredVariables.ts(314,5): error TS7031: Binding element 'value1' implicitly has an 'any' type.
1+
tests/cases/conformance/controlFlow/dependentDestructuredVariables.ts(334,5): error TS7022: 'value1' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer.
2+
tests/cases/conformance/controlFlow/dependentDestructuredVariables.ts(334,5): error TS7031: Binding element 'value1' implicitly has an 'any' type.
33

44

55
==== tests/cases/conformance/controlFlow/dependentDestructuredVariables.ts (2 errors) ====
@@ -39,6 +39,26 @@ tests/cases/conformance/controlFlow/dependentDestructuredVariables.ts(314,5): er
3939
}
4040
}
4141

42+
// repro #50206
43+
function f13<T extends Action>({ kind, payload }: T) {
44+
if (kind === 'A') {
45+
payload.toFixed();
46+
}
47+
if (kind === 'B') {
48+
payload.toUpperCase();
49+
}
50+
}
51+
52+
function f14<T extends Action>(t: T) {
53+
const { kind, payload } = t;
54+
if (kind === 'A') {
55+
payload.toFixed();
56+
}
57+
if (kind === 'B') {
58+
payload.toUpperCase();
59+
}
60+
}
61+
4262
type Action2 =
4363
| { kind: 'A', payload: number | undefined }
4464
| { kind: 'B', payload: string | undefined };

‎tests/baselines/reference/dependentDestructuredVariables.js

+40
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,26 @@ function f12({ kind, payload }: Action) {
3535
}
3636
}
3737

38+
// repro #50206
39+
function f13<T extends Action>({ kind, payload }: T) {
40+
if (kind === 'A') {
41+
payload.toFixed();
42+
}
43+
if (kind === 'B') {
44+
payload.toUpperCase();
45+
}
46+
}
47+
48+
function f14<T extends Action>(t: T) {
49+
const { kind, payload } = t;
50+
if (kind === 'A') {
51+
payload.toFixed();
52+
}
53+
if (kind === 'B') {
54+
payload.toUpperCase();
55+
}
56+
}
57+
3858
type Action2 =
3959
| { kind: 'A', payload: number | undefined }
4060
| { kind: 'B', payload: string | undefined };
@@ -420,6 +440,24 @@ function f12({ kind, payload }) {
420440
payload; // never
421441
}
422442
}
443+
// repro #50206
444+
function f13({ kind, payload }) {
445+
if (kind === 'A') {
446+
payload.toFixed();
447+
}
448+
if (kind === 'B') {
449+
payload.toUpperCase();
450+
}
451+
}
452+
function f14(t) {
453+
const { kind, payload } = t;
454+
if (kind === 'A') {
455+
payload.toFixed();
456+
}
457+
if (kind === 'B') {
458+
payload.toUpperCase();
459+
}
460+
}
423461
function f20({ kind, payload }) {
424462
if (payload) {
425463
if (kind === 'A') {
@@ -662,6 +700,8 @@ type Action = {
662700
declare function f10({ kind, payload }: Action): void;
663701
declare function f11(action: Action): void;
664702
declare function f12({ kind, payload }: Action): void;
703+
declare function f13<T extends Action>({ kind, payload }: T): void;
704+
declare function f14<T extends Action>(t: T): void;
665705
type Action2 = {
666706
kind: 'A';
667707
payload: number | undefined;

0 commit comments

Comments
 (0)
Please sign in to comment.