From e6d1fe49f9db10254e367100ecf29931b275cdcf Mon Sep 17 00:00:00 2001 From: Gabriela Araujo Britto Date: Tue, 15 Feb 2022 20:51:34 +0000 Subject: [PATCH] Cherry-pick PR #47909 into release-4.6 Component commits: f4a5562543 wip: possible fixes 75cb7392f3 pass parameter type to assignBindingElementTypes 4a7de63c83 undo unnecessary changes b618cf9371 update baselines --- src/compiler/checker.ts | 9 ++-- .../reference/narrowingRestGenericCall.js | 34 ++++++++++++++ .../narrowingRestGenericCall.symbols | 44 +++++++++++++++++++ .../reference/narrowingRestGenericCall.types | 42 ++++++++++++++++++ .../compiler/narrowingRestGenericCall.ts | 13 ++++++ 5 files changed, 138 insertions(+), 4 deletions(-) create mode 100644 tests/baselines/reference/narrowingRestGenericCall.js create mode 100644 tests/baselines/reference/narrowingRestGenericCall.symbols create mode 100644 tests/baselines/reference/narrowingRestGenericCall.types create mode 100644 tests/cases/compiler/narrowingRestGenericCall.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a97f3596e9a03..2d90e93d1e92d 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -31832,21 +31832,22 @@ namespace ts { if (links.type === unknownType) { links.type = getTypeFromBindingPattern(declaration.name); } - assignBindingElementTypes(declaration.name); + assignBindingElementTypes(declaration.name, links.type); } } } // When contextual typing assigns a type to a parameter that contains a binding pattern, we also need to push // the destructured type into the contained binding elements. - function assignBindingElementTypes(pattern: BindingPattern) { + function assignBindingElementTypes(pattern: BindingPattern, parentType: Type) { for (const element of pattern.elements) { if (!isOmittedExpression(element)) { + const type = getBindingElementTypeFromParentType(element, parentType); if (element.name.kind === SyntaxKind.Identifier) { - getSymbolLinks(getSymbolOfNode(element)).type = getTypeForBindingElement(element); + getSymbolLinks(getSymbolOfNode(element)).type = type; } else { - assignBindingElementTypes(element.name); + assignBindingElementTypes(element.name, type); } } } diff --git a/tests/baselines/reference/narrowingRestGenericCall.js b/tests/baselines/reference/narrowingRestGenericCall.js new file mode 100644 index 0000000000000..a180bcb364f1a --- /dev/null +++ b/tests/baselines/reference/narrowingRestGenericCall.js @@ -0,0 +1,34 @@ +//// [narrowingRestGenericCall.ts] +interface Slugs { + foo: string; + bar: string; +} + +function call(obj: T, cb: (val: T) => void) { + cb(obj); +} + +declare let obj: Slugs; +call(obj, ({foo, ...rest}) => { + console.log(rest.bar); +}); + +//// [narrowingRestGenericCall.js] +var __rest = (this && this.__rest) || function (s, e) { + var t = {}; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) + t[p] = s[p]; + if (s != null && typeof Object.getOwnPropertySymbols === "function") + for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { + if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) + t[p[i]] = s[p[i]]; + } + return t; +}; +function call(obj, cb) { + cb(obj); +} +call(obj, function (_a) { + var foo = _a.foo, rest = __rest(_a, ["foo"]); + console.log(rest.bar); +}); diff --git a/tests/baselines/reference/narrowingRestGenericCall.symbols b/tests/baselines/reference/narrowingRestGenericCall.symbols new file mode 100644 index 0000000000000..a128942700bc8 --- /dev/null +++ b/tests/baselines/reference/narrowingRestGenericCall.symbols @@ -0,0 +1,44 @@ +=== tests/cases/compiler/narrowingRestGenericCall.ts === +interface Slugs { +>Slugs : Symbol(Slugs, Decl(narrowingRestGenericCall.ts, 0, 0)) + + foo: string; +>foo : Symbol(Slugs.foo, Decl(narrowingRestGenericCall.ts, 0, 17)) + + bar: string; +>bar : Symbol(Slugs.bar, Decl(narrowingRestGenericCall.ts, 1, 14)) +} + +function call(obj: T, cb: (val: T) => void) { +>call : Symbol(call, Decl(narrowingRestGenericCall.ts, 3, 1)) +>T : Symbol(T, Decl(narrowingRestGenericCall.ts, 5, 14)) +>obj : Symbol(obj, Decl(narrowingRestGenericCall.ts, 5, 32)) +>T : Symbol(T, Decl(narrowingRestGenericCall.ts, 5, 14)) +>cb : Symbol(cb, Decl(narrowingRestGenericCall.ts, 5, 39)) +>val : Symbol(val, Decl(narrowingRestGenericCall.ts, 5, 45)) +>T : Symbol(T, Decl(narrowingRestGenericCall.ts, 5, 14)) + + cb(obj); +>cb : Symbol(cb, Decl(narrowingRestGenericCall.ts, 5, 39)) +>obj : Symbol(obj, Decl(narrowingRestGenericCall.ts, 5, 32)) +} + +declare let obj: Slugs; +>obj : Symbol(obj, Decl(narrowingRestGenericCall.ts, 9, 11)) +>Slugs : Symbol(Slugs, Decl(narrowingRestGenericCall.ts, 0, 0)) + +call(obj, ({foo, ...rest}) => { +>call : Symbol(call, Decl(narrowingRestGenericCall.ts, 3, 1)) +>obj : Symbol(obj, Decl(narrowingRestGenericCall.ts, 9, 11)) +>foo : Symbol(foo, Decl(narrowingRestGenericCall.ts, 10, 12)) +>rest : Symbol(rest, Decl(narrowingRestGenericCall.ts, 10, 16)) + + console.log(rest.bar); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>rest.bar : Symbol(Slugs.bar, Decl(narrowingRestGenericCall.ts, 1, 14)) +>rest : Symbol(rest, Decl(narrowingRestGenericCall.ts, 10, 16)) +>bar : Symbol(Slugs.bar, Decl(narrowingRestGenericCall.ts, 1, 14)) + +}); diff --git a/tests/baselines/reference/narrowingRestGenericCall.types b/tests/baselines/reference/narrowingRestGenericCall.types new file mode 100644 index 0000000000000..a04e883ad9c7d --- /dev/null +++ b/tests/baselines/reference/narrowingRestGenericCall.types @@ -0,0 +1,42 @@ +=== tests/cases/compiler/narrowingRestGenericCall.ts === +interface Slugs { + foo: string; +>foo : string + + bar: string; +>bar : string +} + +function call(obj: T, cb: (val: T) => void) { +>call : (obj: T, cb: (val: T) => void) => void +>obj : T +>cb : (val: T) => void +>val : T + + cb(obj); +>cb(obj) : void +>cb : (val: T) => void +>obj : T +} + +declare let obj: Slugs; +>obj : Slugs + +call(obj, ({foo, ...rest}) => { +>call(obj, ({foo, ...rest}) => { console.log(rest.bar);}) : void +>call : (obj: T, cb: (val: T) => void) => void +>obj : Slugs +>({foo, ...rest}) => { console.log(rest.bar);} : ({ foo, ...rest }: Slugs) => void +>foo : string +>rest : { bar: string; } + + console.log(rest.bar); +>console.log(rest.bar) : void +>console.log : (...data: any[]) => void +>console : Console +>log : (...data: any[]) => void +>rest.bar : string +>rest : { bar: string; } +>bar : string + +}); diff --git a/tests/cases/compiler/narrowingRestGenericCall.ts b/tests/cases/compiler/narrowingRestGenericCall.ts new file mode 100644 index 0000000000000..ed74403099e0a --- /dev/null +++ b/tests/cases/compiler/narrowingRestGenericCall.ts @@ -0,0 +1,13 @@ +interface Slugs { + foo: string; + bar: string; +} + +function call(obj: T, cb: (val: T) => void) { + cb(obj); +} + +declare let obj: Slugs; +call(obj, ({foo, ...rest}) => { + console.log(rest.bar); +}); \ No newline at end of file