Skip to content

Commit 5a35509

Browse files
authored
Fixed narrowing based on aliased discriminants coming from destructured parameters (#56860)
1 parent 01a51d2 commit 5a35509

6 files changed

+118
-3
lines changed

src/compiler/checker.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,7 @@ import {
476476
isCallOrNewExpression,
477477
isCallSignatureDeclaration,
478478
isCatchClause,
479+
isCatchClauseVariableDeclaration,
479480
isCatchClauseVariableDeclarationOrBindingElement,
480481
isCheckJsEnabledForFile,
481482
isClassDeclaration,
@@ -27490,7 +27491,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2749027491
case SyntaxKind.ObjectBindingPattern:
2749127492
case SyntaxKind.ArrayBindingPattern:
2749227493
const rootDeclaration = getRootDeclaration(node.parent);
27493-
return isVariableDeclaration(rootDeclaration) && isVarConstLike(rootDeclaration);
27494+
return isParameter(rootDeclaration) || isCatchClauseVariableDeclaration(rootDeclaration)
27495+
? !isSomeSymbolAssigned(rootDeclaration)
27496+
: isVariableDeclaration(rootDeclaration) && isVarConstLike(rootDeclaration);
2749427497
}
2749527498
return false;
2749627499
}

tests/baselines/reference/controlFlowAliasedDiscriminants.errors.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,4 +126,14 @@ controlFlowAliasedDiscriminants.ts(98,19): error TS1360: Type 'string | number'
126126
resp.resp.data satisfies string;
127127
}
128128
}
129+
130+
function bindingPatternInParameter({ data: data1, isSuccess: isSuccess1 }: UseQueryResult<number>) {
131+
const { data: data2, isSuccess: isSuccess2 } = useQuery();
132+
133+
const areSuccess = isSuccess1 && isSuccess2;
134+
if (areSuccess) {
135+
data1.toExponential();
136+
data2.toExponential();
137+
}
138+
}
129139

tests/baselines/reference/controlFlowAliasedDiscriminants.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,20 @@ type Nested = {
104104
resp.resp.data satisfies string;
105105
}
106106
}
107+
108+
function bindingPatternInParameter({ data: data1, isSuccess: isSuccess1 }: UseQueryResult<number>) {
109+
const { data: data2, isSuccess: isSuccess2 } = useQuery();
110+
111+
const areSuccess = isSuccess1 && isSuccess2;
112+
if (areSuccess) {
113+
data1.toExponential();
114+
data2.toExponential();
115+
}
116+
}
107117

108118

109119
//// [controlFlowAliasedDiscriminants.js]
120+
"use strict";
110121
function useQuery() {
111122
return {
112123
isSuccess: false,
@@ -180,3 +191,12 @@ if (areSuccess) {
180191
resp.resp.data;
181192
}
182193
}
194+
function bindingPatternInParameter(_a) {
195+
var data1 = _a.data, isSuccess1 = _a.isSuccess;
196+
var _b = useQuery(), data2 = _b.data, isSuccess2 = _b.isSuccess;
197+
var areSuccess = isSuccess1 && isSuccess2;
198+
if (areSuccess) {
199+
data1.toExponential();
200+
data2.toExponential();
201+
}
202+
}

tests/baselines/reference/controlFlowAliasedDiscriminants.symbols

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,3 +325,38 @@ type Nested = {
325325
}
326326
}
327327

328+
function bindingPatternInParameter({ data: data1, isSuccess: isSuccess1 }: UseQueryResult<number>) {
329+
>bindingPatternInParameter : Symbol(bindingPatternInParameter, Decl(controlFlowAliasedDiscriminants.ts, 102, 1))
330+
>data : Symbol(data, Decl(controlFlowAliasedDiscriminants.ts, 1, 21), Decl(controlFlowAliasedDiscriminants.ts, 4, 20))
331+
>data1 : Symbol(data1, Decl(controlFlowAliasedDiscriminants.ts, 104, 36))
332+
>isSuccess : Symbol(isSuccess, Decl(controlFlowAliasedDiscriminants.ts, 0, 26), Decl(controlFlowAliasedDiscriminants.ts, 3, 5))
333+
>isSuccess1 : Symbol(isSuccess1, Decl(controlFlowAliasedDiscriminants.ts, 104, 49))
334+
>UseQueryResult : Symbol(UseQueryResult, Decl(controlFlowAliasedDiscriminants.ts, 0, 0))
335+
336+
const { data: data2, isSuccess: isSuccess2 } = useQuery();
337+
>data : Symbol(data, Decl(controlFlowAliasedDiscriminants.ts, 1, 21), Decl(controlFlowAliasedDiscriminants.ts, 4, 20))
338+
>data2 : Symbol(data2, Decl(controlFlowAliasedDiscriminants.ts, 105, 9))
339+
>isSuccess : Symbol(isSuccess, Decl(controlFlowAliasedDiscriminants.ts, 0, 26), Decl(controlFlowAliasedDiscriminants.ts, 3, 5))
340+
>isSuccess2 : Symbol(isSuccess2, Decl(controlFlowAliasedDiscriminants.ts, 105, 22))
341+
>useQuery : Symbol(useQuery, Decl(controlFlowAliasedDiscriminants.ts, 6, 2))
342+
343+
const areSuccess = isSuccess1 && isSuccess2;
344+
>areSuccess : Symbol(areSuccess, Decl(controlFlowAliasedDiscriminants.ts, 107, 7))
345+
>isSuccess1 : Symbol(isSuccess1, Decl(controlFlowAliasedDiscriminants.ts, 104, 49))
346+
>isSuccess2 : Symbol(isSuccess2, Decl(controlFlowAliasedDiscriminants.ts, 105, 22))
347+
348+
if (areSuccess) {
349+
>areSuccess : Symbol(areSuccess, Decl(controlFlowAliasedDiscriminants.ts, 107, 7))
350+
351+
data1.toExponential();
352+
>data1.toExponential : Symbol(Number.toExponential, Decl(lib.es5.d.ts, --, --))
353+
>data1 : Symbol(data1, Decl(controlFlowAliasedDiscriminants.ts, 104, 36))
354+
>toExponential : Symbol(Number.toExponential, Decl(lib.es5.d.ts, --, --))
355+
356+
data2.toExponential();
357+
>data2.toExponential : Symbol(Number.toExponential, Decl(lib.es5.d.ts, --, --))
358+
>data2 : Symbol(data2, Decl(controlFlowAliasedDiscriminants.ts, 105, 9))
359+
>toExponential : Symbol(Number.toExponential, Decl(lib.es5.d.ts, --, --))
360+
}
361+
}
362+

tests/baselines/reference/controlFlowAliasedDiscriminants.types

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,3 +376,41 @@ type Nested = {
376376
}
377377
}
378378

379+
function bindingPatternInParameter({ data: data1, isSuccess: isSuccess1 }: UseQueryResult<number>) {
380+
>bindingPatternInParameter : ({ data: data1, isSuccess: isSuccess1 }: UseQueryResult<number>) => void
381+
>data : any
382+
>data1 : number | undefined
383+
>isSuccess : any
384+
>isSuccess1 : boolean
385+
386+
const { data: data2, isSuccess: isSuccess2 } = useQuery();
387+
>data : any
388+
>data2 : number | undefined
389+
>isSuccess : any
390+
>isSuccess2 : boolean
391+
>useQuery() : UseQueryResult<number>
392+
>useQuery : () => UseQueryResult<number>
393+
394+
const areSuccess = isSuccess1 && isSuccess2;
395+
>areSuccess : boolean
396+
>isSuccess1 && isSuccess2 : boolean
397+
>isSuccess1 : boolean
398+
>isSuccess2 : boolean
399+
400+
if (areSuccess) {
401+
>areSuccess : boolean
402+
403+
data1.toExponential();
404+
>data1.toExponential() : string
405+
>data1.toExponential : (fractionDigits?: number | undefined) => string
406+
>data1 : number
407+
>toExponential : (fractionDigits?: number | undefined) => string
408+
409+
data2.toExponential();
410+
>data2.toExponential() : string
411+
>data2.toExponential : (fractionDigits?: number | undefined) => string
412+
>data2 : number
413+
>toExponential : (fractionDigits?: number | undefined) => string
414+
}
415+
}
416+

tests/cases/compiler/controlFlowAliasedDiscriminants.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
// @strictNullChecks: true
2-
// @noImplicitAny: true
1+
// @strict: true
32

43
type UseQueryResult<T> = {
54
isSuccess: false;
@@ -104,3 +103,13 @@ type Nested = {
104103
resp.resp.data satisfies string;
105104
}
106105
}
106+
107+
function bindingPatternInParameter({ data: data1, isSuccess: isSuccess1 }: UseQueryResult<number>) {
108+
const { data: data2, isSuccess: isSuccess2 } = useQuery();
109+
110+
const areSuccess = isSuccess1 && isSuccess2;
111+
if (areSuccess) {
112+
data1.toExponential();
113+
data2.toExponential();
114+
}
115+
}

0 commit comments

Comments
 (0)