Skip to content

Commit fd601dd

Browse files
authored
CFA for dependent parameters typed by generic constraints (microsoft#48411)
* Obtain apparent type in parameter destructuring check * Add regression test
1 parent 3f483d8 commit fd601dd

File tree

5 files changed

+105
-1
lines changed

5 files changed

+105
-1
lines changed

src/compiler/checker.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -25450,7 +25450,7 @@ namespace ts {
2545025450
if (func.parameters.length >= 2 && isContextSensitiveFunctionOrObjectLiteralMethod(func)) {
2545125451
const contextualSignature = getContextualSignature(func);
2545225452
if (contextualSignature && contextualSignature.parameters.length === 1 && signatureHasRestParameter(contextualSignature)) {
25453-
const restType = getTypeOfSymbol(contextualSignature.parameters[0]);
25453+
const restType = getReducedApparentType(getTypeOfSymbol(contextualSignature.parameters[0]));
2545425454
if (restType.flags & TypeFlags.Union && everyType(restType, isTupleType) && !isSymbolAssigned(symbol)) {
2545525455
const narrowedType = getFlowTypeOfReference(func, restType, restType, /*flowContainer*/ undefined, location.flowNode);
2545625456
const index = func.parameters.indexOf(declaration) - (getThisParameter(func) ? 1 : 0);

tests/baselines/reference/dependentDestructuredVariables.js

+23
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,19 @@ let fooAsyncGenM: FooAsyncGenMethod = {
295295
}
296296
}
297297
};
298+
299+
// Repro from #48345
300+
301+
type Func = <T extends ["a", number] | ["b", string]>(...args: T) => void;
302+
303+
const f60: Func = (kind, payload) => {
304+
if (kind === "a") {
305+
payload.toFixed(); // error
306+
}
307+
if (kind === "b") {
308+
payload.toUpperCase(); // error
309+
}
310+
};
298311

299312

300313
//// [dependentDestructuredVariables.js]
@@ -529,6 +542,14 @@ let fooAsyncGenM = {
529542
});
530543
}
531544
};
545+
const f60 = (kind, payload) => {
546+
if (kind === "a") {
547+
payload.toFixed(); // error
548+
}
549+
if (kind === "b") {
550+
payload.toUpperCase(); // error
551+
}
552+
};
532553

533554

534555
//// [dependentDestructuredVariables.d.ts]
@@ -644,3 +665,5 @@ declare type FooAsyncGenMethod = {
644665
]): AsyncGenerator<any, any, any>;
645666
};
646667
declare let fooAsyncGenM: FooAsyncGenMethod;
668+
declare type Func = <T extends ["a", number] | ["b", string]>(...args: T) => void;
669+
declare const f60: Func;

tests/baselines/reference/dependentDestructuredVariables.symbols

+32
Original file line numberDiff line numberDiff line change
@@ -752,3 +752,35 @@ let fooAsyncGenM: FooAsyncGenMethod = {
752752
}
753753
};
754754

755+
// Repro from #48345
756+
757+
type Func = <T extends ["a", number] | ["b", string]>(...args: T) => void;
758+
>Func : Symbol(Func, Decl(dependentDestructuredVariables.ts, 295, 2))
759+
>T : Symbol(T, Decl(dependentDestructuredVariables.ts, 299, 13))
760+
>args : Symbol(args, Decl(dependentDestructuredVariables.ts, 299, 54))
761+
>T : Symbol(T, Decl(dependentDestructuredVariables.ts, 299, 13))
762+
763+
const f60: Func = (kind, payload) => {
764+
>f60 : Symbol(f60, Decl(dependentDestructuredVariables.ts, 301, 5))
765+
>Func : Symbol(Func, Decl(dependentDestructuredVariables.ts, 295, 2))
766+
>kind : Symbol(kind, Decl(dependentDestructuredVariables.ts, 301, 19))
767+
>payload : Symbol(payload, Decl(dependentDestructuredVariables.ts, 301, 24))
768+
769+
if (kind === "a") {
770+
>kind : Symbol(kind, Decl(dependentDestructuredVariables.ts, 301, 19))
771+
772+
payload.toFixed(); // error
773+
>payload.toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --))
774+
>payload : Symbol(payload, Decl(dependentDestructuredVariables.ts, 301, 24))
775+
>toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --))
776+
}
777+
if (kind === "b") {
778+
>kind : Symbol(kind, Decl(dependentDestructuredVariables.ts, 301, 19))
779+
780+
payload.toUpperCase(); // error
781+
>payload.toUpperCase : Symbol(String.toUpperCase, Decl(lib.es5.d.ts, --, --))
782+
>payload : Symbol(payload, Decl(dependentDestructuredVariables.ts, 301, 24))
783+
>toUpperCase : Symbol(String.toUpperCase, Decl(lib.es5.d.ts, --, --))
784+
}
785+
};
786+

tests/baselines/reference/dependentDestructuredVariables.types

+36
Original file line numberDiff line numberDiff line change
@@ -855,3 +855,39 @@ let fooAsyncGenM: FooAsyncGenMethod = {
855855
}
856856
};
857857

858+
// Repro from #48345
859+
860+
type Func = <T extends ["a", number] | ["b", string]>(...args: T) => void;
861+
>Func : Func
862+
>args : T
863+
864+
const f60: Func = (kind, payload) => {
865+
>f60 : Func
866+
>(kind, payload) => { if (kind === "a") { payload.toFixed(); // error } if (kind === "b") { payload.toUpperCase(); // error }} : <T extends ["a", number] | ["b", string]>(kind: T[0], payload: T[1]) => void
867+
>kind : T[0]
868+
>payload : T[1]
869+
870+
if (kind === "a") {
871+
>kind === "a" : boolean
872+
>kind : "a" | "b"
873+
>"a" : "a"
874+
875+
payload.toFixed(); // error
876+
>payload.toFixed() : string
877+
>payload.toFixed : (fractionDigits?: number | undefined) => string
878+
>payload : number
879+
>toFixed : (fractionDigits?: number | undefined) => string
880+
}
881+
if (kind === "b") {
882+
>kind === "b" : boolean
883+
>kind : "a" | "b"
884+
>"b" : "b"
885+
886+
payload.toUpperCase(); // error
887+
>payload.toUpperCase() : string
888+
>payload.toUpperCase : () => string
889+
>payload : string
890+
>toUpperCase : () => string
891+
}
892+
};
893+

tests/cases/conformance/controlFlow/dependentDestructuredVariables.ts

+13
Original file line numberDiff line numberDiff line change
@@ -299,3 +299,16 @@ let fooAsyncGenM: FooAsyncGenMethod = {
299299
}
300300
}
301301
};
302+
303+
// Repro from #48345
304+
305+
type Func = <T extends ["a", number] | ["b", string]>(...args: T) => void;
306+
307+
const f60: Func = (kind, payload) => {
308+
if (kind === "a") {
309+
payload.toFixed(); // error
310+
}
311+
if (kind === "b") {
312+
payload.toUpperCase(); // error
313+
}
314+
};

0 commit comments

Comments
 (0)