From 70f617509ba4e84687751e973368812517dc6b5a Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 24 Mar 2022 16:41:03 -0700 Subject: [PATCH 1/2] Obtain apparent type in parameter destructuring check --- src/compiler/checker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 43dafe03456ab..419ee806de3f6 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -25424,7 +25424,7 @@ namespace ts { if (func.parameters.length >= 2 && isContextSensitiveFunctionOrObjectLiteralMethod(func)) { const contextualSignature = getContextualSignature(func); if (contextualSignature && contextualSignature.parameters.length === 1 && signatureHasRestParameter(contextualSignature)) { - const restType = getTypeOfSymbol(contextualSignature.parameters[0]); + const restType = getReducedApparentType(getTypeOfSymbol(contextualSignature.parameters[0])); if (restType.flags & TypeFlags.Union && everyType(restType, isTupleType) && !isSymbolAssigned(symbol)) { const narrowedType = getFlowTypeOfReference(func, restType, restType, /*flowContainer*/ undefined, location.flowNode); const index = func.parameters.indexOf(declaration) - (getThisParameter(func) ? 1 : 0); From 44e8d7252d5b41c3ca6cb065ae1a885d0c0a6c22 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 24 Mar 2022 16:50:10 -0700 Subject: [PATCH 2/2] Add regression test --- .../dependentDestructuredVariables.js | 23 ++++++++++++ .../dependentDestructuredVariables.symbols | 32 +++++++++++++++++ .../dependentDestructuredVariables.types | 36 +++++++++++++++++++ .../dependentDestructuredVariables.ts | 13 +++++++ 4 files changed, 104 insertions(+) diff --git a/tests/baselines/reference/dependentDestructuredVariables.js b/tests/baselines/reference/dependentDestructuredVariables.js index db312d66704fd..a9f2006ec1e7a 100644 --- a/tests/baselines/reference/dependentDestructuredVariables.js +++ b/tests/baselines/reference/dependentDestructuredVariables.js @@ -295,6 +295,19 @@ let fooAsyncGenM: FooAsyncGenMethod = { } } }; + +// Repro from #48345 + +type Func = (...args: T) => void; + +const f60: Func = (kind, payload) => { + if (kind === "a") { + payload.toFixed(); // error + } + if (kind === "b") { + payload.toUpperCase(); // error + } +}; //// [dependentDestructuredVariables.js] @@ -529,6 +542,14 @@ let fooAsyncGenM = { }); } }; +const f60 = (kind, payload) => { + if (kind === "a") { + payload.toFixed(); // error + } + if (kind === "b") { + payload.toUpperCase(); // error + } +}; //// [dependentDestructuredVariables.d.ts] @@ -644,3 +665,5 @@ declare type FooAsyncGenMethod = { ]): AsyncGenerator; }; declare let fooAsyncGenM: FooAsyncGenMethod; +declare type Func = (...args: T) => void; +declare const f60: Func; diff --git a/tests/baselines/reference/dependentDestructuredVariables.symbols b/tests/baselines/reference/dependentDestructuredVariables.symbols index af1919fc31226..f859b5ee7566f 100644 --- a/tests/baselines/reference/dependentDestructuredVariables.symbols +++ b/tests/baselines/reference/dependentDestructuredVariables.symbols @@ -752,3 +752,35 @@ let fooAsyncGenM: FooAsyncGenMethod = { } }; +// Repro from #48345 + +type Func = (...args: T) => void; +>Func : Symbol(Func, Decl(dependentDestructuredVariables.ts, 295, 2)) +>T : Symbol(T, Decl(dependentDestructuredVariables.ts, 299, 13)) +>args : Symbol(args, Decl(dependentDestructuredVariables.ts, 299, 54)) +>T : Symbol(T, Decl(dependentDestructuredVariables.ts, 299, 13)) + +const f60: Func = (kind, payload) => { +>f60 : Symbol(f60, Decl(dependentDestructuredVariables.ts, 301, 5)) +>Func : Symbol(Func, Decl(dependentDestructuredVariables.ts, 295, 2)) +>kind : Symbol(kind, Decl(dependentDestructuredVariables.ts, 301, 19)) +>payload : Symbol(payload, Decl(dependentDestructuredVariables.ts, 301, 24)) + + if (kind === "a") { +>kind : Symbol(kind, Decl(dependentDestructuredVariables.ts, 301, 19)) + + payload.toFixed(); // error +>payload.toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) +>payload : Symbol(payload, Decl(dependentDestructuredVariables.ts, 301, 24)) +>toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) + } + if (kind === "b") { +>kind : Symbol(kind, Decl(dependentDestructuredVariables.ts, 301, 19)) + + payload.toUpperCase(); // error +>payload.toUpperCase : Symbol(String.toUpperCase, Decl(lib.es5.d.ts, --, --)) +>payload : Symbol(payload, Decl(dependentDestructuredVariables.ts, 301, 24)) +>toUpperCase : Symbol(String.toUpperCase, Decl(lib.es5.d.ts, --, --)) + } +}; + diff --git a/tests/baselines/reference/dependentDestructuredVariables.types b/tests/baselines/reference/dependentDestructuredVariables.types index 3f0ee678974f8..bfc8a5f2fb882 100644 --- a/tests/baselines/reference/dependentDestructuredVariables.types +++ b/tests/baselines/reference/dependentDestructuredVariables.types @@ -855,3 +855,39 @@ let fooAsyncGenM: FooAsyncGenMethod = { } }; +// Repro from #48345 + +type Func = (...args: T) => void; +>Func : Func +>args : T + +const f60: Func = (kind, payload) => { +>f60 : Func +>(kind, payload) => { if (kind === "a") { payload.toFixed(); // error } if (kind === "b") { payload.toUpperCase(); // error }} : (kind: T[0], payload: T[1]) => void +>kind : T[0] +>payload : T[1] + + if (kind === "a") { +>kind === "a" : boolean +>kind : "a" | "b" +>"a" : "a" + + payload.toFixed(); // error +>payload.toFixed() : string +>payload.toFixed : (fractionDigits?: number | undefined) => string +>payload : number +>toFixed : (fractionDigits?: number | undefined) => string + } + if (kind === "b") { +>kind === "b" : boolean +>kind : "a" | "b" +>"b" : "b" + + payload.toUpperCase(); // error +>payload.toUpperCase() : string +>payload.toUpperCase : () => string +>payload : string +>toUpperCase : () => string + } +}; + diff --git a/tests/cases/conformance/controlFlow/dependentDestructuredVariables.ts b/tests/cases/conformance/controlFlow/dependentDestructuredVariables.ts index 2b1d64fc3bac8..b56045e7ec061 100644 --- a/tests/cases/conformance/controlFlow/dependentDestructuredVariables.ts +++ b/tests/cases/conformance/controlFlow/dependentDestructuredVariables.ts @@ -299,3 +299,16 @@ let fooAsyncGenM: FooAsyncGenMethod = { } } }; + +// Repro from #48345 + +type Func = (...args: T) => void; + +const f60: Func = (kind, payload) => { + if (kind === "a") { + payload.toFixed(); // error + } + if (kind === "b") { + payload.toUpperCase(); // error + } +};