Add support for destructuring well-known and late-bound names (#23297)

* Add support for destructuring well-known and late-bound names

* Add test of not present late bound prop
This commit is contained in:
Wesley Wigham 2018-04-10 18:21:24 -07:00 committed by GitHub
parent 1243d1a9ba
commit b2e0c4bea6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 125 additions and 3 deletions

View File

@ -4174,14 +4174,17 @@ namespace ts {
else {
// Use explicitly specified property name ({ p: xxx } form), or otherwise the implied name ({ p } form)
const name = declaration.propertyName || <Identifier>declaration.name;
if (isComputedNonLiteralName(name)) {
// computed properties with non-literal names are treated as 'any'
const isLate = isLateBindableName(name);
const isWellKnown = isComputedPropertyName(name) && isWellKnownSymbolSyntactically(name.expression);
if (!isLate && !isWellKnown && isComputedNonLiteralName(name)) {
return anyType;
}
// Use type of the specified property, or otherwise, for a numeric name, the type of the numeric index signature,
// or otherwise the type of the string index signature.
const text = getTextOfPropertyName(name);
const text = isLate ? getLateBoundNameFromType(checkComputedPropertyName(name as ComputedPropertyName) as LiteralType | UniqueESSymbolType) :
isWellKnown ? getPropertyNameForKnownSymbolName(idText(((name as ComputedPropertyName).expression as PropertyAccessExpression).name)) :
getTextOfPropertyName(name);
// Relax null check on ambient destructuring parameters, since the parameters have no implementation and are just documentation
if (strictNullChecks && declaration.flags & NodeFlags.Ambient && isParameterDeclaration(declaration)) {

View File

@ -0,0 +1,18 @@
tests/cases/compiler/destructuredLateBoundNameHasCorrectTypes.ts(11,7): error TS2459: Type '{ prop: string; }' has no property '[notPresent]' and no string index signature.
==== tests/cases/compiler/destructuredLateBoundNameHasCorrectTypes.ts (1 errors) ====
let { [Symbol.iterator]: destructured } = [];
void destructured;
const named = "prop";
let { [named]: computed } = { prop: "b" };
void computed;
const notPresent = "prop2";
let { [notPresent]: computed2 } = { prop: "b" };
~~~~~~~~~~~~
!!! error TS2459: Type '{ prop: string; }' has no property '[notPresent]' and no string index signature.

View File

@ -0,0 +1,22 @@
//// [destructuredLateBoundNameHasCorrectTypes.ts]
let { [Symbol.iterator]: destructured } = [];
void destructured;
const named = "prop";
let { [named]: computed } = { prop: "b" };
void computed;
const notPresent = "prop2";
let { [notPresent]: computed2 } = { prop: "b" };
//// [destructuredLateBoundNameHasCorrectTypes.js]
let { [Symbol.iterator]: destructured } = [];
void destructured;
const named = "prop";
let { [named]: computed } = { prop: "b" };
void computed;
const notPresent = "prop2";
let { [notPresent]: computed2 } = { prop: "b" };

View File

@ -0,0 +1,29 @@
=== tests/cases/compiler/destructuredLateBoundNameHasCorrectTypes.ts ===
let { [Symbol.iterator]: destructured } = [];
>Symbol.iterator : Symbol(SymbolConstructor.iterator, Decl(lib.es2015.iterable.d.ts, --, --))
>Symbol : Symbol(Symbol, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --))
>iterator : Symbol(SymbolConstructor.iterator, Decl(lib.es2015.iterable.d.ts, --, --))
>destructured : Symbol(destructured, Decl(destructuredLateBoundNameHasCorrectTypes.ts, 0, 5))
void destructured;
>destructured : Symbol(destructured, Decl(destructuredLateBoundNameHasCorrectTypes.ts, 0, 5))
const named = "prop";
>named : Symbol(named, Decl(destructuredLateBoundNameHasCorrectTypes.ts, 3, 5))
let { [named]: computed } = { prop: "b" };
>named : Symbol(named, Decl(destructuredLateBoundNameHasCorrectTypes.ts, 3, 5))
>computed : Symbol(computed, Decl(destructuredLateBoundNameHasCorrectTypes.ts, 5, 5))
>prop : Symbol(prop, Decl(destructuredLateBoundNameHasCorrectTypes.ts, 5, 29))
void computed;
>computed : Symbol(computed, Decl(destructuredLateBoundNameHasCorrectTypes.ts, 5, 5))
const notPresent = "prop2";
>notPresent : Symbol(notPresent, Decl(destructuredLateBoundNameHasCorrectTypes.ts, 8, 5))
let { [notPresent]: computed2 } = { prop: "b" };
>notPresent : Symbol(notPresent, Decl(destructuredLateBoundNameHasCorrectTypes.ts, 8, 5))
>computed2 : Symbol(computed2, Decl(destructuredLateBoundNameHasCorrectTypes.ts, 10, 5))
>prop : Symbol(prop, Decl(destructuredLateBoundNameHasCorrectTypes.ts, 10, 35))

View File

@ -0,0 +1,38 @@
=== tests/cases/compiler/destructuredLateBoundNameHasCorrectTypes.ts ===
let { [Symbol.iterator]: destructured } = [];
>Symbol.iterator : symbol
>Symbol : SymbolConstructor
>iterator : symbol
>destructured : () => IterableIterator<undefined>
>[] : undefined[]
void destructured;
>void destructured : undefined
>destructured : () => IterableIterator<undefined>
const named = "prop";
>named : "prop"
>"prop" : "prop"
let { [named]: computed } = { prop: "b" };
>named : "prop"
>computed : string
>{ prop: "b" } : { prop: string; }
>prop : string
>"b" : "b"
void computed;
>void computed : undefined
>computed : string
const notPresent = "prop2";
>notPresent : "prop2"
>"prop2" : "prop2"
let { [notPresent]: computed2 } = { prop: "b" };
>notPresent : "prop2"
>computed2 : any
>{ prop: "b" } : { prop: string; }
>prop : string
>"b" : "b"

View File

@ -0,0 +1,12 @@
// @target: es6
let { [Symbol.iterator]: destructured } = [];
void destructured;
const named = "prop";
let { [named]: computed } = { prop: "b" };
void computed;
const notPresent = "prop2";
let { [notPresent]: computed2 } = { prop: "b" };