From f555261d7a6c8695de4953288965823c3089d33c Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 1 Nov 2018 12:33:18 -0700 Subject: [PATCH 01/12] Add Rest type to lib.d.ts --- src/lib/es5.d.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/lib/es5.d.ts b/src/lib/es5.d.ts index c8e99f0d1dbaf..70e7e805899d6 100644 --- a/src/lib/es5.d.ts +++ b/src/lib/es5.d.ts @@ -1416,6 +1416,13 @@ type Pick = { [P in K]: T[P]; }; +/** + * From T, omit a set of properties whose keys are in the union K + */ +type Rest = { + [P in Exclude]: T[P]; +}; + /** * Construct a type with a set of properties K of type T */ From 6f8959b86b7b984bf5557429d6c39bb00ba38916 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 1 Nov 2018 12:41:39 -0700 Subject: [PATCH 02/12] Use Rest for rest properties in object destructuring --- src/compiler/checker.ts | 59 +++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 29 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 2418c75f0cb68..6bde3775b944c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -517,6 +517,7 @@ namespace ts { let deferredGlobalTemplateStringsArrayType: ObjectType; let deferredGlobalImportMetaType: ObjectType; let deferredGlobalExtractSymbol: Symbol; + let deferredGlobalRestSymbol: Symbol; const allPotentiallyUnusedIdentifiers = createMap(); // key is file name @@ -4596,26 +4597,18 @@ namespace ts { if (source.flags & TypeFlags.Never) { return emptyObjectType; } - if (source.flags & TypeFlags.Union) { return mapType(source, t => getRestType(t, properties, symbol)); } - - const members = createSymbolTable(); - const names = createUnderscoreEscapedMap(); - for (const name of properties) { - names.set(getTextOfPropertyName(name), true); + const restTypeAlias = getGlobalRestSymbol(); + if (!restTypeAlias) { + return errorType; } - for (const prop of getPropertiesOfType(source)) { - if (!names.has(prop.escapedName) - && !(getDeclarationModifierFlagsFromSymbol(prop) & (ModifierFlags.Private | ModifierFlags.Protected)) - && isSpreadableProperty(prop)) { - members.set(prop.escapedName, getSpreadSymbol(prop)); - } + const omitTypes = getUnionType(map(properties, getLiteralTypeFromPropertyName)); + if (omitTypes.flags & TypeFlags.Never) { + return source; } - const stringIndexInfo = getIndexInfoOfType(source, IndexKind.String); - const numberIndexInfo = getIndexInfoOfType(source, IndexKind.Number); - return createAnonymousType(symbol, members, emptyArray, emptyArray, stringIndexInfo, numberIndexInfo); + return getTypeAliasInstantiation(restTypeAlias, [source, omitTypes]); } /** Return the inferred type for a binding element */ @@ -4639,7 +4632,7 @@ namespace ts { let type: Type | undefined; if (pattern.kind === SyntaxKind.ObjectBindingPattern) { if (declaration.dotDotDotToken) { - if (parentType.flags & TypeFlags.Unknown || !isValidSpreadType(parentType) || isGenericObjectType(parentType)) { + if (parentType.flags & TypeFlags.Unknown || !isValidSpreadType(parentType)) { error(declaration, Diagnostics.Rest_types_may_only_be_created_from_object_types); return errorType; } @@ -6823,7 +6816,7 @@ namespace ts { if (isMappedTypeWithKeyofConstraintDeclaration(type)) { // We have a { [P in keyof T]: X } for (const prop of getPropertiesOfType(modifiersType)) { - addMemberForKeyType(getLiteralTypeFromPropertyName(prop, include)); + addMemberForKeyType(getLiteralTypeFromProperty(prop, include)); } if (modifiersType.flags & TypeFlags.Any || getIndexInfoOfType(modifiersType, IndexKind.String)) { addMemberForKeyType(stringType); @@ -8674,6 +8667,10 @@ namespace ts { return deferredGlobalExtractSymbol || (deferredGlobalExtractSymbol = getGlobalSymbol("Extract" as __String, SymbolFlags.TypeAlias, Diagnostics.Cannot_find_global_type_0)!); // TODO: GH#18217 } + function getGlobalRestSymbol(): Symbol { + return deferredGlobalRestSymbol || (deferredGlobalRestSymbol = getGlobalSymbol("Rest" as __String, SymbolFlags.TypeAlias, Diagnostics.Cannot_find_global_type_0)!); // TODO: GH#18217 + } + /** * Instantiates a global type that is generic with some element type, and returns that instantiation. */ @@ -9256,14 +9253,18 @@ namespace ts { type.resolvedIndexType || (type.resolvedIndexType = createIndexType(type, /*stringsOnly*/ false)); } - function getLiteralTypeFromPropertyName(prop: Symbol, include: TypeFlags) { + function getLiteralTypeFromPropertyName(name: PropertyName) { + return isComputedPropertyName(name) ? checkComputedPropertyName(name) : + isIdentifier(name) ? getLiteralType(unescapeLeadingUnderscores(name.escapedText)) : + checkExpression(name); + } + + function getLiteralTypeFromProperty(prop: Symbol, include: TypeFlags) { if (!(getDeclarationModifierFlagsFromSymbol(prop) & ModifierFlags.NonPublicAccessibilityModifier)) { let type = getLateBoundSymbol(prop).nameType; if (!type && !isKnownSymbol(prop)) { - const name = prop.valueDeclaration && getNameOfDeclaration(prop.valueDeclaration); - type = name && isNumericLiteral(name) ? getLiteralType(+name.text) : - name && name.kind === SyntaxKind.ComputedPropertyName && isNumericLiteral(name.expression) ? getLiteralType(+name.expression.text) : - getLiteralType(symbolName(prop)); + const name = prop.valueDeclaration && getNameOfDeclaration(prop.valueDeclaration) as PropertyName; + type = name && getLiteralTypeFromPropertyName(name) || getLiteralType(symbolName(prop)); } if (type && type.flags & include) { return type; @@ -9272,8 +9273,8 @@ namespace ts { return neverType; } - function getLiteralTypeFromPropertyNames(type: Type, include: TypeFlags) { - return getUnionType(map(getPropertiesOfType(type), t => getLiteralTypeFromPropertyName(t, include))); + function getLiteralTypeFromProperties(type: Type, include: TypeFlags) { + return getUnionType(map(getPropertiesOfType(type), t => getLiteralTypeFromProperty(t, include))); } function getNonEnumNumberIndexInfo(type: Type) { @@ -9288,10 +9289,10 @@ namespace ts { getObjectFlags(type) & ObjectFlags.Mapped ? getConstraintTypeFromMappedType(type) : type === wildcardType ? wildcardType : type.flags & TypeFlags.Any ? keyofConstraintType : - stringsOnly ? getIndexInfoOfType(type, IndexKind.String) ? stringType : getLiteralTypeFromPropertyNames(type, TypeFlags.StringLiteral) : - getIndexInfoOfType(type, IndexKind.String) ? getUnionType([stringType, numberType, getLiteralTypeFromPropertyNames(type, TypeFlags.UniqueESSymbol)]) : - getNonEnumNumberIndexInfo(type) ? getUnionType([numberType, getLiteralTypeFromPropertyNames(type, TypeFlags.StringLiteral | TypeFlags.UniqueESSymbol)]) : - getLiteralTypeFromPropertyNames(type, TypeFlags.StringOrNumberLiteralOrUnique); + stringsOnly ? getIndexInfoOfType(type, IndexKind.String) ? stringType : getLiteralTypeFromProperties(type, TypeFlags.StringLiteral) : + getIndexInfoOfType(type, IndexKind.String) ? getUnionType([stringType, numberType, getLiteralTypeFromProperties(type, TypeFlags.UniqueESSymbol)]) : + getNonEnumNumberIndexInfo(type) ? getUnionType([numberType, getLiteralTypeFromProperties(type, TypeFlags.StringLiteral | TypeFlags.UniqueESSymbol)]) : + getLiteralTypeFromProperties(type, TypeFlags.StringOrNumberLiteralOrUnique); } function getExtractStringType(type: Type) { @@ -10976,7 +10977,7 @@ namespace ts { if (!length(node.properties)) return; for (const prop of node.properties) { if (isSpreadAssignment(prop)) continue; - const type = getLiteralTypeFromPropertyName(getSymbolOfNode(prop), TypeFlags.StringOrNumberLiteralOrUnique); + const type = getLiteralTypeFromProperty(getSymbolOfNode(prop), TypeFlags.StringOrNumberLiteralOrUnique); if (!type || (type.flags & TypeFlags.Never)) { continue; } From 18f80b89088fb853dc1accf8b81fcdcf7e074442 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 1 Nov 2018 12:42:32 -0700 Subject: [PATCH 03/12] Accept new baselines --- .../asyncFunctionTempVariableScoping.types | 2 +- ...ropertyNamesContextualType8_ES5.errors.txt | 19 +++--- ...ropertyNamesContextualType8_ES6.errors.txt | 19 +++--- .../expressionTypeNodeShouldError.types | 12 ++-- ...turingDoesNotElideFollowingStatement.types | 2 +- .../importHelpersInAmbientContext.types | 4 +- .../intersectionsOfLargeUnions.types | 6 +- .../intersectionsOfLargeUnions2.types | 6 +- .../modularizeLibrary_Dom.iterable.types | 4 +- .../nonPrimitiveAccessProperty.types | 2 +- .../baselines/reference/objectRest.errors.txt | 58 +++++++++++++++++++ tests/baselines/reference/objectRest.types | 34 +++++------ .../reference/objectRestAssignment.types | 8 +-- .../baselines/reference/objectRestForOf.types | 6 +- .../reference/objectRestNegative.errors.txt | 9 +-- .../reference/objectRestNegative.types | 10 ++-- .../reference/objectRestParameter.symbols | 12 ++-- .../reference/objectRestParameter.types | 18 +++--- .../reference/objectRestParameterES5.symbols | 12 ++-- .../reference/objectRestParameterES5.types | 18 +++--- .../reference/objectRestReadonly.symbols | 4 +- .../reference/objectRestReadonly.types | 4 +- ...InitializerBeforeDestructuringEmit.symbols | 8 +-- ...erInitializerBeforeDestructuringEmit.types | 8 +-- .../parserOverloadOnConstants1.types | 8 +-- .../restInvalidArgumentType.errors.txt | 20 +------ .../reference/restInvalidArgumentType.types | 14 ++--- .../unusedLocalsAndObjectSpread.types | 12 ++-- 28 files changed, 189 insertions(+), 150 deletions(-) create mode 100644 tests/baselines/reference/objectRest.errors.txt diff --git a/tests/baselines/reference/asyncFunctionTempVariableScoping.types b/tests/baselines/reference/asyncFunctionTempVariableScoping.types index 30b2399490368..cc477523cb914 100644 --- a/tests/baselines/reference/asyncFunctionTempVariableScoping.types +++ b/tests/baselines/reference/asyncFunctionTempVariableScoping.types @@ -5,7 +5,7 @@ async ({ foo, bar, ...rest }) => bar(await foo); >async ({ foo, bar, ...rest }) => bar(await foo) : ({ foo, bar, ...rest }: { [x: string]: any; foo: any; bar: any; }) => Promise >foo : any >bar : any ->rest : { [x: string]: any; } +>rest : Rest<{ [x: string]: any; foo: any; bar: any; }, "foo" | "bar"> >bar(await foo) : any >bar : any >await foo : any diff --git a/tests/baselines/reference/computedPropertyNamesContextualType8_ES5.errors.txt b/tests/baselines/reference/computedPropertyNamesContextualType8_ES5.errors.txt index 56e374f0d5352..ee36609095a04 100644 --- a/tests/baselines/reference/computedPropertyNamesContextualType8_ES5.errors.txt +++ b/tests/baselines/reference/computedPropertyNamesContextualType8_ES5.errors.txt @@ -1,20 +1,21 @@ -tests/cases/conformance/es6/computedProperties/computedPropertyNamesContextualType8_ES5.ts(7,5): error TS2418: Type of computed property's value is 'string', which is not assignable to type 'boolean'. -tests/cases/conformance/es6/computedProperties/computedPropertyNamesContextualType8_ES5.ts(8,5): error TS2418: Type of computed property's value is 'number', which is not assignable to type 'boolean'. +tests/cases/conformance/es6/computedProperties/computedPropertyNamesContextualType8_ES5.ts(6,5): error TS2322: Type '{ [x: string]: string | number; }' is not assignable to type 'I'. + Index signatures are incompatible. + Type 'string | number' is not assignable to type 'boolean'. + Type 'string' is not assignable to type 'boolean'. -==== tests/cases/conformance/es6/computedProperties/computedPropertyNamesContextualType8_ES5.ts (2 errors) ==== +==== tests/cases/conformance/es6/computedProperties/computedPropertyNamesContextualType8_ES5.ts (1 errors) ==== interface I { [s: string]: boolean; [s: number]: boolean; } var o: I = { + ~ +!!! error TS2322: Type '{ [x: string]: string | number; }' is not assignable to type 'I'. +!!! error TS2322: Index signatures are incompatible. +!!! error TS2322: Type 'string | number' is not assignable to type 'boolean'. +!!! error TS2322: Type 'string' is not assignable to type 'boolean'. [""+"foo"]: "", - ~~~~~~~~~~ -!!! error TS2418: Type of computed property's value is 'string', which is not assignable to type 'boolean'. -!!! related TS6501 tests/cases/conformance/es6/computedProperties/computedPropertyNamesContextualType8_ES5.ts:2:5: The expected type comes from this index signature. [""+"bar"]: 0 - ~~~~~~~~~~ -!!! error TS2418: Type of computed property's value is 'number', which is not assignable to type 'boolean'. -!!! related TS6501 tests/cases/conformance/es6/computedProperties/computedPropertyNamesContextualType8_ES5.ts:2:5: The expected type comes from this index signature. } \ No newline at end of file diff --git a/tests/baselines/reference/computedPropertyNamesContextualType8_ES6.errors.txt b/tests/baselines/reference/computedPropertyNamesContextualType8_ES6.errors.txt index c24b53eaa1709..1048fd2e119e7 100644 --- a/tests/baselines/reference/computedPropertyNamesContextualType8_ES6.errors.txt +++ b/tests/baselines/reference/computedPropertyNamesContextualType8_ES6.errors.txt @@ -1,20 +1,21 @@ -tests/cases/conformance/es6/computedProperties/computedPropertyNamesContextualType8_ES6.ts(7,5): error TS2418: Type of computed property's value is 'string', which is not assignable to type 'boolean'. -tests/cases/conformance/es6/computedProperties/computedPropertyNamesContextualType8_ES6.ts(8,5): error TS2418: Type of computed property's value is 'number', which is not assignable to type 'boolean'. +tests/cases/conformance/es6/computedProperties/computedPropertyNamesContextualType8_ES6.ts(6,5): error TS2322: Type '{ [x: string]: string | number; }' is not assignable to type 'I'. + Index signatures are incompatible. + Type 'string | number' is not assignable to type 'boolean'. + Type 'string' is not assignable to type 'boolean'. -==== tests/cases/conformance/es6/computedProperties/computedPropertyNamesContextualType8_ES6.ts (2 errors) ==== +==== tests/cases/conformance/es6/computedProperties/computedPropertyNamesContextualType8_ES6.ts (1 errors) ==== interface I { [s: string]: boolean; [s: number]: boolean; } var o: I = { + ~ +!!! error TS2322: Type '{ [x: string]: string | number; }' is not assignable to type 'I'. +!!! error TS2322: Index signatures are incompatible. +!!! error TS2322: Type 'string | number' is not assignable to type 'boolean'. +!!! error TS2322: Type 'string' is not assignable to type 'boolean'. [""+"foo"]: "", - ~~~~~~~~~~ -!!! error TS2418: Type of computed property's value is 'string', which is not assignable to type 'boolean'. -!!! related TS6501 tests/cases/conformance/es6/computedProperties/computedPropertyNamesContextualType8_ES6.ts:2:5: The expected type comes from this index signature. [""+"bar"]: 0 - ~~~~~~~~~~ -!!! error TS2418: Type of computed property's value is 'number', which is not assignable to type 'boolean'. -!!! related TS6501 tests/cases/conformance/es6/computedProperties/computedPropertyNamesContextualType8_ES6.ts:2:5: The expected type comes from this index signature. } \ No newline at end of file diff --git a/tests/baselines/reference/expressionTypeNodeShouldError.types b/tests/baselines/reference/expressionTypeNodeShouldError.types index 45c12d7c8ffe9..90707d4db507b 100644 --- a/tests/baselines/reference/expressionTypeNodeShouldError.types +++ b/tests/baselines/reference/expressionTypeNodeShouldError.types @@ -31,9 +31,9 @@ class C { const nodes = document.getElementsByTagName("li"); >nodes : HTMLCollectionOf >document.getElementsByTagName("li") : HTMLCollectionOf ->document.getElementsByTagName : { (qualifiedName: K): HTMLCollectionOf; (qualifiedName: K): HTMLCollectionOf; (qualifiedName: string): HTMLCollectionOf; } +>document.getElementsByTagName : { (qualifiedName: K): HTMLCollectionOf; (qualifiedName: K): HTMLCollectionOf; (qualifiedName: string): HTMLCollectionOf; } >document : Document ->getElementsByTagName : { (qualifiedName: K): HTMLCollectionOf; (qualifiedName: K): HTMLCollectionOf; (qualifiedName: string): HTMLCollectionOf; } +>getElementsByTagName : { (qualifiedName: K): HTMLCollectionOf; (qualifiedName: K): HTMLCollectionOf; (qualifiedName: string): HTMLCollectionOf; } >"li" : "li" type ItemType = "".typeof(nodes.item(0)); @@ -72,9 +72,9 @@ class C2 { const nodes2 = document.getElementsByTagName("li"); >nodes2 : HTMLCollectionOf >document.getElementsByTagName("li") : HTMLCollectionOf ->document.getElementsByTagName : { (qualifiedName: K): HTMLCollectionOf; (qualifiedName: K): HTMLCollectionOf; (qualifiedName: string): HTMLCollectionOf; } +>document.getElementsByTagName : { (qualifiedName: K): HTMLCollectionOf; (qualifiedName: K): HTMLCollectionOf; (qualifiedName: string): HTMLCollectionOf; } >document : Document ->getElementsByTagName : { (qualifiedName: K): HTMLCollectionOf; (qualifiedName: K): HTMLCollectionOf; (qualifiedName: string): HTMLCollectionOf; } +>getElementsByTagName : { (qualifiedName: K): HTMLCollectionOf; (qualifiedName: K): HTMLCollectionOf; (qualifiedName: string): HTMLCollectionOf; } >"li" : "li" type ItemType2 = 4..typeof(nodes.item(0)); @@ -114,9 +114,9 @@ class C3 { const nodes3 = document.getElementsByTagName("li"); >nodes3 : HTMLCollectionOf >document.getElementsByTagName("li") : HTMLCollectionOf ->document.getElementsByTagName : { (qualifiedName: K): HTMLCollectionOf; (qualifiedName: K): HTMLCollectionOf; (qualifiedName: string): HTMLCollectionOf; } +>document.getElementsByTagName : { (qualifiedName: K): HTMLCollectionOf; (qualifiedName: K): HTMLCollectionOf; (qualifiedName: string): HTMLCollectionOf; } >document : Document ->getElementsByTagName : { (qualifiedName: K): HTMLCollectionOf; (qualifiedName: K): HTMLCollectionOf; (qualifiedName: string): HTMLCollectionOf; } +>getElementsByTagName : { (qualifiedName: K): HTMLCollectionOf; (qualifiedName: K): HTMLCollectionOf; (qualifiedName: string): HTMLCollectionOf; } >"li" : "li" type ItemType3 = true.typeof(nodes.item(0)); diff --git a/tests/baselines/reference/forLoopWithDestructuringDoesNotElideFollowingStatement.types b/tests/baselines/reference/forLoopWithDestructuringDoesNotElideFollowingStatement.types index 246c6d2e7dbcf..600c4f9d71757 100644 --- a/tests/baselines/reference/forLoopWithDestructuringDoesNotElideFollowingStatement.types +++ b/tests/baselines/reference/forLoopWithDestructuringDoesNotElideFollowingStatement.types @@ -10,7 +10,7 @@ let array = [{a: 0, b: 1}] for (let { a, ...rest } of array) >a : number ->rest : { b: number; } +>rest : Rest<{ a: number; b: number; }, "a"> >array : { a: number; b: number; }[] void a diff --git a/tests/baselines/reference/importHelpersInAmbientContext.types b/tests/baselines/reference/importHelpersInAmbientContext.types index 0c3365d7d9355..794bdb2e41810 100644 --- a/tests/baselines/reference/importHelpersInAmbientContext.types +++ b/tests/baselines/reference/importHelpersInAmbientContext.types @@ -33,7 +33,7 @@ interface Foo { } export var { a, ...x } : Foo; >a : number ->x : { b: string; } +>x : Rest === tests/cases/compiler/b.ts === export {}; @@ -72,7 +72,7 @@ declare namespace N { } export var { a, ...x } : Foo; >a : number ->x : { b: string; } +>x : Rest } === tests/cases/compiler/tslib.d.ts === diff --git a/tests/baselines/reference/intersectionsOfLargeUnions.types b/tests/baselines/reference/intersectionsOfLargeUnions.types index 06d01c0c6b2df..26f93ac79db08 100644 --- a/tests/baselines/reference/intersectionsOfLargeUnions.types +++ b/tests/baselines/reference/intersectionsOfLargeUnions.types @@ -24,7 +24,7 @@ export function assertIsElement(node: Node | null): node is Element { } export function assertNodeTagName< ->assertNodeTagName : (node: Node | null, tagName: T) => node is U +>assertNodeTagName : (node: Node | null, tagName: T) => node is U T extends keyof ElementTagNameMap, U extends ElementTagNameMap[T]>(node: Node | null, tagName: T): node is U { @@ -56,7 +56,7 @@ export function assertNodeTagName< } export function assertNodeProperty< ->assertNodeProperty : (node: Node | null, tagName: T, prop: P, value: V) => void +>assertNodeProperty : (node: Node | null, tagName: T, prop: P, value: V) => void T extends keyof ElementTagNameMap, P extends keyof ElementTagNameMap[T], @@ -69,7 +69,7 @@ export function assertNodeProperty< if (assertNodeTagName(node, tagName)) { >assertNodeTagName(node, tagName) : boolean ->assertNodeTagName : (node: Node | null, tagName: T) => node is U +>assertNodeTagName : (node: Node | null, tagName: T) => node is U >node : Node | null >tagName : T diff --git a/tests/baselines/reference/intersectionsOfLargeUnions2.types b/tests/baselines/reference/intersectionsOfLargeUnions2.types index 82160fb235e18..277806ae314aa 100644 --- a/tests/baselines/reference/intersectionsOfLargeUnions2.types +++ b/tests/baselines/reference/intersectionsOfLargeUnions2.types @@ -38,7 +38,7 @@ export function assertIsElement(node: Node | null): node is Element { } export function assertNodeTagName< ->assertNodeTagName : (node: Node | null, tagName: T) => node is U +>assertNodeTagName : (node: Node | null, tagName: T) => node is U T extends keyof ElementTagNameMap, U extends ElementTagNameMap[T]>(node: Node | null, tagName: T): node is U { @@ -70,7 +70,7 @@ export function assertNodeTagName< } export function assertNodeProperty< ->assertNodeProperty : (node: Node | null, tagName: T, prop: P, value: V) => void +>assertNodeProperty : (node: Node | null, tagName: T, prop: P, value: V) => void T extends keyof ElementTagNameMap, P extends keyof ElementTagNameMap[T], @@ -83,7 +83,7 @@ export function assertNodeProperty< if (assertNodeTagName(node, tagName)) { >assertNodeTagName(node, tagName) : boolean ->assertNodeTagName : (node: Node | null, tagName: T) => node is U +>assertNodeTagName : (node: Node | null, tagName: T) => node is U >node : Node | null >tagName : T diff --git a/tests/baselines/reference/modularizeLibrary_Dom.iterable.types b/tests/baselines/reference/modularizeLibrary_Dom.iterable.types index e2ba3e7a30086..70c6a6cb5b91f 100644 --- a/tests/baselines/reference/modularizeLibrary_Dom.iterable.types +++ b/tests/baselines/reference/modularizeLibrary_Dom.iterable.types @@ -2,9 +2,9 @@ for (const element of document.getElementsByTagName("a")) { >element : HTMLAnchorElement >document.getElementsByTagName("a") : HTMLCollectionOf ->document.getElementsByTagName : { (qualifiedName: K): HTMLCollectionOf; (qualifiedName: K): HTMLCollectionOf; (qualifiedName: string): HTMLCollectionOf; } +>document.getElementsByTagName : { (qualifiedName: K): HTMLCollectionOf; (qualifiedName: K): HTMLCollectionOf; (qualifiedName: string): HTMLCollectionOf; } >document : Document ->getElementsByTagName : { (qualifiedName: K): HTMLCollectionOf; (qualifiedName: K): HTMLCollectionOf; (qualifiedName: string): HTMLCollectionOf; } +>getElementsByTagName : { (qualifiedName: K): HTMLCollectionOf; (qualifiedName: K): HTMLCollectionOf; (qualifiedName: string): HTMLCollectionOf; } >"a" : "a" element.href; diff --git a/tests/baselines/reference/nonPrimitiveAccessProperty.types b/tests/baselines/reference/nonPrimitiveAccessProperty.types index 900df294d9b30..5218aa20fdafb 100644 --- a/tests/baselines/reference/nonPrimitiveAccessProperty.types +++ b/tests/baselines/reference/nonPrimitiveAccessProperty.types @@ -19,6 +19,6 @@ var { destructuring } = a; // error >a : object var { ...rest } = a; // ok ->rest : {} +>rest : object >a : object diff --git a/tests/baselines/reference/objectRest.errors.txt b/tests/baselines/reference/objectRest.errors.txt new file mode 100644 index 0000000000000..dfea8b96b96b9 --- /dev/null +++ b/tests/baselines/reference/objectRest.errors.txt @@ -0,0 +1,58 @@ +tests/cases/conformance/types/rest/objectRest.ts(43,57): error TS2403: Subsequent variable declarations must have the same type. Variable 'o' must be of type '{ a: number; b: string; }', but here has type 'Rest<{ a: number; b: string; }, string>'. +tests/cases/conformance/types/rest/objectRest.ts(44,53): error TS2322: Type 'Rest<{ a: number; b: string; }, string>' is not assignable to type '{ a: number; b: string; }'. + Property 'a' is missing in type 'Rest<{ a: number; b: string; }, string>'. + + +==== tests/cases/conformance/types/rest/objectRest.ts (2 errors) ==== + var o = { a: 1, b: 'no' } + var { ...clone } = o; + var { a, ...justB } = o; + var { a, b: renamed, ...empty } = o; + var { ['b']: renamed, ...justA } = o; + var { 'b': renamed, ...justA } = o; + var { b: { '0': n, '1': oooo }, ...justA } = o; + + let o2 = { c: 'terrible idea?', d: 'yes' }; + var { d: renamed, ...d } = o2; + + let nestedrest: { x: number, n1: { y: number, n2: { z: number, n3: { n4: number } } }, rest: number, restrest: number }; + var { x, n1: { y, n2: { z, n3: { ...nr } } }, ...restrest } = nestedrest; + + let complex: { x: { ka, ki }, y: number }; + var { x: { ka, ...nested }, y: other, ...rest } = complex; + ({x: { ka, ...nested }, y: other, ...rest} = complex); + var { x, ...fresh } = { x: 1, y: 2 }; + ({ x, ...fresh } = { x: 1, y: 2 }); + + class Removable { + private x: number; + protected y: number; + set z(value: number) { } + get both(): number { return 12 } + set both(value: number) { } + m() { } + removed: string; + remainder: string; + } + interface I { + m(): void; + removed: string; + remainder: string; + } + var removable = new Removable(); + var { removed, ...removableRest } = removable; + var i: I = removable; + var { removed, ...removableRest2 } = i; + + let computed = 'b'; + let computed2 = 'a'; + var { [computed]: stillNotGreat, [computed2]: soSo, ...o } = o; + ~ +!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'o' must be of type '{ a: number; b: string; }', but here has type 'Rest<{ a: number; b: string; }, string>'. + ({ [computed]: stillNotGreat, [computed2]: soSo, ...o } = o); + ~ +!!! error TS2322: Type 'Rest<{ a: number; b: string; }, string>' is not assignable to type '{ a: number; b: string; }'. +!!! error TS2322: Property 'a' is missing in type 'Rest<{ a: number; b: string; }, string>'. + + var noContextualType = ({ aNumber = 12, ...notEmptyObject }) => aNumber + notEmptyObject.anythingGoes; + \ No newline at end of file diff --git a/tests/baselines/reference/objectRest.types b/tests/baselines/reference/objectRest.types index cb50daf9c4b0a..e664c5e64cda2 100644 --- a/tests/baselines/reference/objectRest.types +++ b/tests/baselines/reference/objectRest.types @@ -13,32 +13,32 @@ var { ...clone } = o; var { a, ...justB } = o; >a : number ->justB : { b: string; } +>justB : Rest<{ a: number; b: string; }, "a"> >o : { a: number; b: string; } var { a, b: renamed, ...empty } = o; >a : number >b : any >renamed : string ->empty : {} +>empty : Rest<{ a: number; b: string; }, "a" | "b"> >o : { a: number; b: string; } var { ['b']: renamed, ...justA } = o; >'b' : "b" >renamed : string ->justA : { a: number; } +>justA : Rest<{ a: number; b: string; }, "b"> >o : { a: number; b: string; } var { 'b': renamed, ...justA } = o; >renamed : string ->justA : { a: number; } +>justA : Rest<{ a: number; b: string; }, "b"> >o : { a: number; b: string; } var { b: { '0': n, '1': oooo }, ...justA } = o; >b : any >n : string >oooo : string ->justA : { a: number; } +>justA : Rest<{ a: number; b: string; }, "b"> >o : { a: number; b: string; } let o2 = { c: 'terrible idea?', d: 'yes' }; @@ -52,7 +52,7 @@ let o2 = { c: 'terrible idea?', d: 'yes' }; var { d: renamed, ...d } = o2; >d : any >renamed : string ->d : { c: string; } +>d : Rest<{ c: string; d: string; }, "d"> >o2 : { c: string; d: string; } let nestedrest: { x: number, n1: { y: number, n2: { z: number, n3: { n4: number } } }, rest: number, restrest: number }; @@ -75,7 +75,7 @@ var { x, n1: { y, n2: { z, n3: { ...nr } } }, ...restrest } = nestedrest; >z : number >n3 : any >nr : { n4: number; } ->restrest : { rest: number; restrest: number; } +>restrest : Rest<{ x: number; n1: { y: number; n2: { z: number; n3: { n4: number; }; }; }; rest: number; restrest: number; }, "x" | "n1"> >nestedrest : { x: number; n1: { y: number; n2: { z: number; n3: { n4: number; }; }; }; rest: number; restrest: number; } let complex: { x: { ka, ki }, y: number }; @@ -88,10 +88,10 @@ let complex: { x: { ka, ki }, y: number }; var { x: { ka, ...nested }, y: other, ...rest } = complex; >x : any >ka : any ->nested : { ki: any; } +>nested : Rest<{ ka: any; ki: any; }, "ka"> >y : any >other : number ->rest : {} +>rest : Rest<{ x: { ka: any; ki: any; }; y: number; }, "x" | "y"> >complex : { x: { ka: any; ki: any; }; y: number; } ({x: { ka, ...nested }, y: other, ...rest} = complex); @@ -101,15 +101,15 @@ var { x: { ka, ...nested }, y: other, ...rest } = complex; >x : { ki: any; ka: any; } >{ ka, ...nested } : { ki: any; ka: any; } >ka : any ->nested : { ki: any; } +>nested : Rest<{ ka: any; ki: any; }, "ka"> >y : number >other : number ->rest : {} +>rest : Rest<{ x: { ka: any; ki: any; }; y: number; }, "x" | "y"> >complex : { x: { ka: any; ki: any; }; y: number; } var { x, ...fresh } = { x: 1, y: 2 }; >x : number ->fresh : { y: number; } +>fresh : Rest<{ x: number; y: number; }, "x"> >{ x: 1, y: 2 } : { x: number; y: number; } >x : number >1 : 1 @@ -121,7 +121,7 @@ var { x, ...fresh } = { x: 1, y: 2 }; >{ x, ...fresh } = { x: 1, y: 2 } : { x: number; y: number; } >{ x, ...fresh } : { y: number; x: number; } >x : number ->fresh : { y: number; } +>fresh : Rest<{ x: number; y: number; }, "x"> >{ x: 1, y: 2 } : { x: number; y: number; } >x : number >1 : 1 @@ -175,7 +175,7 @@ var removable = new Removable(); var { removed, ...removableRest } = removable; >removed : string ->removableRest : { remainder: string; } +>removableRest : Rest >removable : Removable var i: I = removable; @@ -184,7 +184,7 @@ var i: I = removable; var { removed, ...removableRest2 } = i; >removed : string ->removableRest2 : { m(): void; remainder: string; } +>removableRest2 : Rest >i : I let computed = 'b'; @@ -221,10 +221,10 @@ var noContextualType = ({ aNumber = 12, ...notEmptyObject }) => aNumber + notEmp >({ aNumber = 12, ...notEmptyObject }) => aNumber + notEmptyObject.anythingGoes : ({ aNumber, ...notEmptyObject }: { [x: string]: any; aNumber?: number; }) => any >aNumber : number >12 : 12 ->notEmptyObject : { [x: string]: any; } +>notEmptyObject : Rest<{ [x: string]: any; aNumber?: number; }, "aNumber"> >aNumber + notEmptyObject.anythingGoes : any >aNumber : number >notEmptyObject.anythingGoes : any ->notEmptyObject : { [x: string]: any; } +>notEmptyObject : Rest<{ [x: string]: any; aNumber?: number; }, "aNumber"> >anythingGoes : any diff --git a/tests/baselines/reference/objectRestAssignment.types b/tests/baselines/reference/objectRestAssignment.types index c0c84b6d5e349..04507f688cb2b 100644 --- a/tests/baselines/reference/objectRestAssignment.types +++ b/tests/baselines/reference/objectRestAssignment.types @@ -52,8 +52,8 @@ var { a: [{ ...nested2 }, ...y], b: { z, ...c }, ...rest2 } = overEmit; >y : { ka: string; x: string; }[] >b : any >z : string ->c : { ki: string; ku: string; } ->rest2 : { ke: string; ko: string; } +>c : Rest<{ z: string; ki: string; ku: string; }, "z"> +>rest2 : Rest<{ a: { ka: string; x: string; }[]; b: { z: string; ki: string; ku: string; }; ke: string; ko: string; }, "a" | "b"> >overEmit : { a: { ka: string; x: string; }[]; b: { z: string; ki: string; ku: string; }; ke: string; ko: string; } ({ a: [{ ...nested2 }, ...y], b: { z, ...c }, ...rest2 } = overEmit); @@ -69,7 +69,7 @@ var { a: [{ ...nested2 }, ...y], b: { z, ...c }, ...rest2 } = overEmit; >b : { ki: string; ku: string; z: string; } >{ z, ...c } : { ki: string; ku: string; z: string; } >z : string ->c : { ki: string; ku: string; } ->rest2 : { ke: string; ko: string; } +>c : Rest<{ z: string; ki: string; ku: string; }, "z"> +>rest2 : Rest<{ a: { ka: string; x: string; }[]; b: { z: string; ki: string; ku: string; }; ke: string; ko: string; }, "a" | "b"> >overEmit : { a: { ka: string; x: string; }[]; b: { z: string; ki: string; ku: string; }; ke: string; ko: string; } diff --git a/tests/baselines/reference/objectRestForOf.types b/tests/baselines/reference/objectRestForOf.types index 30e10999bc78e..107a38ecea655 100644 --- a/tests/baselines/reference/objectRestForOf.types +++ b/tests/baselines/reference/objectRestForOf.types @@ -6,13 +6,13 @@ let array: { x: number, y: string }[]; for (let { x, ...restOf } of array) { >x : number ->restOf : { y: string; } +>restOf : Rest<{ x: number; y: string; }, "x"> >array : { x: number; y: string; }[] [x, restOf]; ->[x, restOf] : (number | { y: string; })[] +>[x, restOf] : (number | Rest<{ x: number; y: string; }, "x">)[] >x : number ->restOf : { y: string; } +>restOf : Rest<{ x: number; y: string; }, "x"> } let xx: number; >xx : number diff --git a/tests/baselines/reference/objectRestNegative.errors.txt b/tests/baselines/reference/objectRestNegative.errors.txt index fef99187d55b4..8e599f26639b4 100644 --- a/tests/baselines/reference/objectRestNegative.errors.txt +++ b/tests/baselines/reference/objectRestNegative.errors.txt @@ -1,15 +1,14 @@ tests/cases/conformance/types/rest/objectRestNegative.ts(2,10): error TS2462: A rest element must be last in a destructuring pattern. -tests/cases/conformance/types/rest/objectRestNegative.ts(6,10): error TS2322: Type '{ a: number; }' is not assignable to type '{ a: string; }'. +tests/cases/conformance/types/rest/objectRestNegative.ts(6,10): error TS2322: Type 'Rest<{ a: number; b: string; }, "b">' is not assignable to type '{ a: string; }'. Types of property 'a' are incompatible. Type 'number' is not assignable to type 'string'. tests/cases/conformance/types/rest/objectRestNegative.ts(9,31): error TS2462: A rest element must be last in a destructuring pattern. tests/cases/conformance/types/rest/objectRestNegative.ts(11,30): error TS7008: Member 'x' implicitly has an 'any' type. tests/cases/conformance/types/rest/objectRestNegative.ts(11,33): error TS7008: Member 'y' implicitly has an 'any' type. -tests/cases/conformance/types/rest/objectRestNegative.ts(12,17): error TS2700: Rest types may only be created from object types. tests/cases/conformance/types/rest/objectRestNegative.ts(17,9): error TS2701: The target of an object rest assignment must be a variable or a property access. -==== tests/cases/conformance/types/rest/objectRestNegative.ts (7 errors) ==== +==== tests/cases/conformance/types/rest/objectRestNegative.ts (6 errors) ==== let o = { a: 1, b: 'no' }; var { ...mustBeLast, a } = o; ~~~~~~~~~~ @@ -19,7 +18,7 @@ tests/cases/conformance/types/rest/objectRestNegative.ts(17,9): error TS2701: Th let notAssignable: { a: string }; ({ b, ...notAssignable } = o); ~~~~~~~~~~~~~ -!!! error TS2322: Type '{ a: number; }' is not assignable to type '{ a: string; }'. +!!! error TS2322: Type 'Rest<{ a: number; b: string; }, "b">' is not assignable to type '{ a: string; }'. !!! error TS2322: Types of property 'a' are incompatible. !!! error TS2322: Type 'number' is not assignable to type 'string'. @@ -34,8 +33,6 @@ tests/cases/conformance/types/rest/objectRestNegative.ts(17,9): error TS2701: Th ~ !!! error TS7008: Member 'y' implicitly has an 'any' type. let { x, ...rest } = t; - ~~~~ -!!! error TS2700: Rest types may only be created from object types. return rest; } diff --git a/tests/baselines/reference/objectRestNegative.types b/tests/baselines/reference/objectRestNegative.types index dff6388d6090f..8287f870599fc 100644 --- a/tests/baselines/reference/objectRestNegative.types +++ b/tests/baselines/reference/objectRestNegative.types @@ -8,7 +8,7 @@ let o = { a: 1, b: 'no' }; >'no' : "no" var { ...mustBeLast, a } = o; ->mustBeLast : { b: string; } +>mustBeLast : Rest<{ a: number; b: string; }, "a"> >a : number >o : { a: number; b: string; } @@ -30,24 +30,24 @@ let notAssignable: { a: string }; function stillMustBeLast({ ...mustBeLast, a }: { a: number, b: string }): void { >stillMustBeLast : ({ ...mustBeLast, a }: { a: number; b: string; }) => void ->mustBeLast : { b: string; } +>mustBeLast : Rest<{ a: number; b: string; }, "a"> >a : number >a : number >b : string } function generic(t: T) { ->generic : (t: T) => any +>generic : (t: T) => Rest >x : any >y : any >t : T let { x, ...rest } = t; >x : any ->rest : any +>rest : Rest >t : T return rest; ->rest : any +>rest : Rest } let rest: { b: string } diff --git a/tests/baselines/reference/objectRestParameter.symbols b/tests/baselines/reference/objectRestParameter.symbols index f629f46e8e994..536689ae5679d 100644 --- a/tests/baselines/reference/objectRestParameter.symbols +++ b/tests/baselines/reference/objectRestParameter.symbols @@ -21,9 +21,9 @@ suddenly(({ x: a, ...rest }) => rest.y); >x : Symbol(x, Decl(objectRestParameter.ts, 3, 34)) >a : Symbol(a, Decl(objectRestParameter.ts, 4, 11)) >rest : Symbol(rest, Decl(objectRestParameter.ts, 4, 17)) ->rest.y : Symbol(y, Decl(objectRestParameter.ts, 3, 48)) +>rest.y : Symbol(y) >rest : Symbol(rest, Decl(objectRestParameter.ts, 4, 17)) ->y : Symbol(y, Decl(objectRestParameter.ts, 3, 48)) +>y : Symbol(y) suddenly(({ x: { z = 12, ...nested }, ...rest } = { x: { z: 1, ka: 1 }, y: 'noo' }) => rest.y + nested.ka); >suddenly : Symbol(suddenly, Decl(objectRestParameter.ts, 1, 1)) @@ -35,12 +35,12 @@ suddenly(({ x: { z = 12, ...nested }, ...rest } = { x: { z: 1, ka: 1 }, y: 'noo' >z : Symbol(z, Decl(objectRestParameter.ts, 5, 56)) >ka : Symbol(ka, Decl(objectRestParameter.ts, 5, 62)) >y : Symbol(y, Decl(objectRestParameter.ts, 5, 71)) ->rest.y : Symbol(y, Decl(objectRestParameter.ts, 3, 48)) +>rest.y : Symbol(y) >rest : Symbol(rest, Decl(objectRestParameter.ts, 5, 37)) ->y : Symbol(y, Decl(objectRestParameter.ts, 3, 48)) ->nested.ka : Symbol(ka, Decl(objectRestParameter.ts, 3, 42)) +>y : Symbol(y) +>nested.ka : Symbol(ka) >nested : Symbol(nested, Decl(objectRestParameter.ts, 5, 24)) ->ka : Symbol(ka, Decl(objectRestParameter.ts, 3, 42)) +>ka : Symbol(ka) class C { >C : Symbol(C, Decl(objectRestParameter.ts, 5, 107)) diff --git a/tests/baselines/reference/objectRestParameter.types b/tests/baselines/reference/objectRestParameter.types index 831ac9df59f9a..c3d1c4f01f21a 100644 --- a/tests/baselines/reference/objectRestParameter.types +++ b/tests/baselines/reference/objectRestParameter.types @@ -2,7 +2,7 @@ function cloneAgain({ a, ...clone }: { a: number, b: string }): void { >cloneAgain : ({ a, ...clone }: { a: number; b: string; }) => void >a : number ->clone : { b: string; } +>clone : Rest<{ a: number; b: string; }, "a"> >a : number >b : string } @@ -22,9 +22,9 @@ suddenly(({ x: a, ...rest }) => rest.y); >({ x: a, ...rest }) => rest.y : ({ x: a, ...rest }: { x: { z: any; ka: any; }; y: string; }) => string >x : any >a : { z: any; ka: any; } ->rest : { y: string; } +>rest : Rest<{ x: { z: any; ka: any; }; y: string; }, "x"> >rest.y : string ->rest : { y: string; } +>rest : Rest<{ x: { z: any; ka: any; }; y: string; }, "x"> >y : string suddenly(({ x: { z = 12, ...nested }, ...rest } = { x: { z: 1, ka: 1 }, y: 'noo' }) => rest.y + nested.ka); @@ -34,8 +34,8 @@ suddenly(({ x: { z = 12, ...nested }, ...rest } = { x: { z: 1, ka: 1 }, y: 'noo' >x : any >z : any >12 : 12 ->nested : { ka: any; } ->rest : { y: string; } +>nested : Rest<{ z: any; ka: any; }, "z"> +>rest : Rest<{ x: { z: any; ka: any; }; y: string; }, "x"> >{ x: { z: 1, ka: 1 }, y: 'noo' } : { x: { z: number; ka: number; }; y: string; } >x : { z: number; ka: number; } >{ z: 1, ka: 1 } : { z: number; ka: number; } @@ -47,10 +47,10 @@ suddenly(({ x: { z = 12, ...nested }, ...rest } = { x: { z: 1, ka: 1 }, y: 'noo' >'noo' : "noo" >rest.y + nested.ka : string >rest.y : string ->rest : { y: string; } +>rest : Rest<{ x: { z: any; ka: any; }; y: string; }, "x"> >y : string >nested.ka : any ->nested : { ka: any; } +>nested : Rest<{ z: any; ka: any; }, "z"> >ka : any class C { @@ -59,7 +59,7 @@ class C { m({ a, ...clone }: { a: number, b: string}): void { >m : ({ a, ...clone }: { a: number; b: string; }) => void >a : number ->clone : { b: string; } +>clone : Rest<{ a: number; b: string; }, "a"> >a : number >b : string @@ -68,7 +68,7 @@ class C { set p({ a, ...clone }: { a: number, b: string}) { >p : { a: number; b: string; } >a : number ->clone : { b: string; } +>clone : Rest<{ a: number; b: string; }, "a"> >a : number >b : string diff --git a/tests/baselines/reference/objectRestParameterES5.symbols b/tests/baselines/reference/objectRestParameterES5.symbols index 4c6b8115169b8..c397e13779907 100644 --- a/tests/baselines/reference/objectRestParameterES5.symbols +++ b/tests/baselines/reference/objectRestParameterES5.symbols @@ -21,9 +21,9 @@ suddenly(({ x: a, ...rest }) => rest.y); >x : Symbol(x, Decl(objectRestParameterES5.ts, 3, 34)) >a : Symbol(a, Decl(objectRestParameterES5.ts, 4, 11)) >rest : Symbol(rest, Decl(objectRestParameterES5.ts, 4, 17)) ->rest.y : Symbol(y, Decl(objectRestParameterES5.ts, 3, 48)) +>rest.y : Symbol(y) >rest : Symbol(rest, Decl(objectRestParameterES5.ts, 4, 17)) ->y : Symbol(y, Decl(objectRestParameterES5.ts, 3, 48)) +>y : Symbol(y) suddenly(({ x: { z = 12, ...nested }, ...rest } = { x: { z: 1, ka: 1 }, y: 'noo' }) => rest.y + nested.ka); >suddenly : Symbol(suddenly, Decl(objectRestParameterES5.ts, 1, 1)) @@ -35,12 +35,12 @@ suddenly(({ x: { z = 12, ...nested }, ...rest } = { x: { z: 1, ka: 1 }, y: 'noo' >z : Symbol(z, Decl(objectRestParameterES5.ts, 5, 56)) >ka : Symbol(ka, Decl(objectRestParameterES5.ts, 5, 62)) >y : Symbol(y, Decl(objectRestParameterES5.ts, 5, 71)) ->rest.y : Symbol(y, Decl(objectRestParameterES5.ts, 3, 48)) +>rest.y : Symbol(y) >rest : Symbol(rest, Decl(objectRestParameterES5.ts, 5, 37)) ->y : Symbol(y, Decl(objectRestParameterES5.ts, 3, 48)) ->nested.ka : Symbol(ka, Decl(objectRestParameterES5.ts, 3, 42)) +>y : Symbol(y) +>nested.ka : Symbol(ka) >nested : Symbol(nested, Decl(objectRestParameterES5.ts, 5, 24)) ->ka : Symbol(ka, Decl(objectRestParameterES5.ts, 3, 42)) +>ka : Symbol(ka) class C { >C : Symbol(C, Decl(objectRestParameterES5.ts, 5, 107)) diff --git a/tests/baselines/reference/objectRestParameterES5.types b/tests/baselines/reference/objectRestParameterES5.types index 1b8dd29e29ef6..329f69bedcd40 100644 --- a/tests/baselines/reference/objectRestParameterES5.types +++ b/tests/baselines/reference/objectRestParameterES5.types @@ -2,7 +2,7 @@ function cloneAgain({ a, ...clone }: { a: number, b: string }): void { >cloneAgain : ({ a, ...clone }: { a: number; b: string; }) => void >a : number ->clone : { b: string; } +>clone : Rest<{ a: number; b: string; }, "a"> >a : number >b : string } @@ -22,9 +22,9 @@ suddenly(({ x: a, ...rest }) => rest.y); >({ x: a, ...rest }) => rest.y : ({ x: a, ...rest }: { x: { z: any; ka: any; }; y: string; }) => string >x : any >a : { z: any; ka: any; } ->rest : { y: string; } +>rest : Rest<{ x: { z: any; ka: any; }; y: string; }, "x"> >rest.y : string ->rest : { y: string; } +>rest : Rest<{ x: { z: any; ka: any; }; y: string; }, "x"> >y : string suddenly(({ x: { z = 12, ...nested }, ...rest } = { x: { z: 1, ka: 1 }, y: 'noo' }) => rest.y + nested.ka); @@ -34,8 +34,8 @@ suddenly(({ x: { z = 12, ...nested }, ...rest } = { x: { z: 1, ka: 1 }, y: 'noo' >x : any >z : any >12 : 12 ->nested : { ka: any; } ->rest : { y: string; } +>nested : Rest<{ z: any; ka: any; }, "z"> +>rest : Rest<{ x: { z: any; ka: any; }; y: string; }, "x"> >{ x: { z: 1, ka: 1 }, y: 'noo' } : { x: { z: number; ka: number; }; y: string; } >x : { z: number; ka: number; } >{ z: 1, ka: 1 } : { z: number; ka: number; } @@ -47,10 +47,10 @@ suddenly(({ x: { z = 12, ...nested }, ...rest } = { x: { z: 1, ka: 1 }, y: 'noo' >'noo' : "noo" >rest.y + nested.ka : string >rest.y : string ->rest : { y: string; } +>rest : Rest<{ x: { z: any; ka: any; }; y: string; }, "x"> >y : string >nested.ka : any ->nested : { ka: any; } +>nested : Rest<{ z: any; ka: any; }, "z"> >ka : any class C { @@ -59,7 +59,7 @@ class C { m({ a, ...clone }: { a: number, b: string}): void { >m : ({ a, ...clone }: { a: number; b: string; }) => void >a : number ->clone : { b: string; } +>clone : Rest<{ a: number; b: string; }, "a"> >a : number >b : string @@ -68,7 +68,7 @@ class C { set p({ a, ...clone }: { a: number, b: string}) { >p : { a: number; b: string; } >a : number ->clone : { b: string; } +>clone : Rest<{ a: number; b: string; }, "a"> >a : number >b : string diff --git a/tests/baselines/reference/objectRestReadonly.symbols b/tests/baselines/reference/objectRestReadonly.symbols index f2a7504e9b59e..ef32c8b616a86 100644 --- a/tests/baselines/reference/objectRestReadonly.symbols +++ b/tests/baselines/reference/objectRestReadonly.symbols @@ -34,7 +34,7 @@ const { foo, ...rest } = obj >obj : Symbol(obj, Decl(objectRestReadonly.ts, 7, 5)) delete rest.baz ->rest.baz : Symbol(baz, Decl(objectRestReadonly.ts, 2, 13)) +>rest.baz : Symbol(baz) >rest : Symbol(rest, Decl(objectRestReadonly.ts, 13, 12)) ->baz : Symbol(baz, Decl(objectRestReadonly.ts, 2, 13)) +>baz : Symbol(baz) diff --git a/tests/baselines/reference/objectRestReadonly.types b/tests/baselines/reference/objectRestReadonly.types index 5f015aeb1e5f5..d21b5793c66cc 100644 --- a/tests/baselines/reference/objectRestReadonly.types +++ b/tests/baselines/reference/objectRestReadonly.types @@ -32,12 +32,12 @@ const obj: Readonly = { const { foo, ...rest } = obj >foo : string ->rest : { baz: string; quux: string; } +>rest : Rest, "foo"> >obj : Readonly delete rest.baz >delete rest.baz : boolean >rest.baz : string ->rest : { baz: string; quux: string; } +>rest : Rest, "foo"> >baz : string diff --git a/tests/baselines/reference/parameterInitializerBeforeDestructuringEmit.symbols b/tests/baselines/reference/parameterInitializerBeforeDestructuringEmit.symbols index 857310bf87c96..e3e6dcdc9a406 100644 --- a/tests/baselines/reference/parameterInitializerBeforeDestructuringEmit.symbols +++ b/tests/baselines/reference/parameterInitializerBeforeDestructuringEmit.symbols @@ -18,9 +18,9 @@ function foobar({ bar = {}, ...opts }: Foo = {}) { "use strict"; "Some other prologue"; opts.baz(bar); ->opts.baz : Symbol(Foo.baz, Decl(parameterInitializerBeforeDestructuringEmit.ts, 1, 14)) +>opts.baz : Symbol(baz) >opts : Symbol(opts, Decl(parameterInitializerBeforeDestructuringEmit.ts, 5, 27)) ->baz : Symbol(Foo.baz, Decl(parameterInitializerBeforeDestructuringEmit.ts, 1, 14)) +>baz : Symbol(baz) >bar : Symbol(bar, Decl(parameterInitializerBeforeDestructuringEmit.ts, 5, 17)) } @@ -35,9 +35,9 @@ class C { "use strict"; "Some other prologue"; opts.baz(bar); ->opts.baz : Symbol(Foo.baz, Decl(parameterInitializerBeforeDestructuringEmit.ts, 1, 14)) +>opts.baz : Symbol(baz) >opts : Symbol(opts, Decl(parameterInitializerBeforeDestructuringEmit.ts, 12, 27)) ->baz : Symbol(Foo.baz, Decl(parameterInitializerBeforeDestructuringEmit.ts, 1, 14)) +>baz : Symbol(baz) >bar : Symbol(bar, Decl(parameterInitializerBeforeDestructuringEmit.ts, 12, 17)) } } diff --git a/tests/baselines/reference/parameterInitializerBeforeDestructuringEmit.types b/tests/baselines/reference/parameterInitializerBeforeDestructuringEmit.types index bbdf5580a6014..28f71d1362b75 100644 --- a/tests/baselines/reference/parameterInitializerBeforeDestructuringEmit.types +++ b/tests/baselines/reference/parameterInitializerBeforeDestructuringEmit.types @@ -11,7 +11,7 @@ function foobar({ bar = {}, ...opts }: Foo = {}) { >foobar : ({ bar, ...opts }?: Foo) => void >bar : any >{} : {} ->opts : { baz?: any; } +>opts : Rest >{} : {} "use strict"; @@ -23,7 +23,7 @@ function foobar({ bar = {}, ...opts }: Foo = {}) { opts.baz(bar); >opts.baz(bar) : any >opts.baz : any ->opts : { baz?: any; } +>opts : Rest >baz : any >bar : any } @@ -34,7 +34,7 @@ class C { constructor({ bar = {}, ...opts }: Foo = {}) { >bar : any >{} : {} ->opts : { baz?: any; } +>opts : Rest >{} : {} "use strict"; @@ -46,7 +46,7 @@ class C { opts.baz(bar); >opts.baz(bar) : any >opts.baz : any ->opts : { baz?: any; } +>opts : Rest >baz : any >bar : any } diff --git a/tests/baselines/reference/parserOverloadOnConstants1.types b/tests/baselines/reference/parserOverloadOnConstants1.types index 6cac9a704a9f6..2a865af7ba7e4 100644 --- a/tests/baselines/reference/parserOverloadOnConstants1.types +++ b/tests/baselines/reference/parserOverloadOnConstants1.types @@ -1,18 +1,18 @@ === tests/cases/conformance/parser/ecmascript5/parserOverloadOnConstants1.ts === interface Document { createElement(tagName: string): HTMLElement; ->createElement : { (tagName: K, options?: ElementCreationOptions): HTMLElementTagNameMap[K]; (tagName: K, options?: ElementCreationOptions): HTMLElementDeprecatedTagNameMap[K]; (tagName: string, options?: ElementCreationOptions): HTMLElement; (tagName: string): HTMLElement; (tagName: "canvas"): HTMLCanvasElement; (tagName: "div"): HTMLDivElement; (tagName: "span"): HTMLSpanElement; } +>createElement : { (tagName: K, options?: ElementCreationOptions): HTMLElementTagNameMap[K]; (tagName: K, options?: ElementCreationOptions): HTMLElementDeprecatedTagNameMap[K]; (tagName: string, options?: ElementCreationOptions): HTMLElement; (tagName: string): HTMLElement; (tagName: "canvas"): HTMLCanvasElement; (tagName: "div"): HTMLDivElement; (tagName: "span"): HTMLSpanElement; } >tagName : string createElement(tagName: 'canvas'): HTMLCanvasElement; ->createElement : { (tagName: K, options?: ElementCreationOptions): HTMLElementTagNameMap[K]; (tagName: K, options?: ElementCreationOptions): HTMLElementDeprecatedTagNameMap[K]; (tagName: string, options?: ElementCreationOptions): HTMLElement; (tagName: string): HTMLElement; (tagName: "canvas"): HTMLCanvasElement; (tagName: "div"): HTMLDivElement; (tagName: "span"): HTMLSpanElement; } +>createElement : { (tagName: K, options?: ElementCreationOptions): HTMLElementTagNameMap[K]; (tagName: K, options?: ElementCreationOptions): HTMLElementDeprecatedTagNameMap[K]; (tagName: string, options?: ElementCreationOptions): HTMLElement; (tagName: string): HTMLElement; (tagName: "canvas"): HTMLCanvasElement; (tagName: "div"): HTMLDivElement; (tagName: "span"): HTMLSpanElement; } >tagName : "canvas" createElement(tagName: 'div'): HTMLDivElement; ->createElement : { (tagName: K, options?: ElementCreationOptions): HTMLElementTagNameMap[K]; (tagName: K, options?: ElementCreationOptions): HTMLElementDeprecatedTagNameMap[K]; (tagName: string, options?: ElementCreationOptions): HTMLElement; (tagName: string): HTMLElement; (tagName: "canvas"): HTMLCanvasElement; (tagName: "div"): HTMLDivElement; (tagName: "span"): HTMLSpanElement; } +>createElement : { (tagName: K, options?: ElementCreationOptions): HTMLElementTagNameMap[K]; (tagName: K, options?: ElementCreationOptions): HTMLElementDeprecatedTagNameMap[K]; (tagName: string, options?: ElementCreationOptions): HTMLElement; (tagName: string): HTMLElement; (tagName: "canvas"): HTMLCanvasElement; (tagName: "div"): HTMLDivElement; (tagName: "span"): HTMLSpanElement; } >tagName : "div" createElement(tagName: 'span'): HTMLSpanElement; ->createElement : { (tagName: K, options?: ElementCreationOptions): HTMLElementTagNameMap[K]; (tagName: K, options?: ElementCreationOptions): HTMLElementDeprecatedTagNameMap[K]; (tagName: string, options?: ElementCreationOptions): HTMLElement; (tagName: string): HTMLElement; (tagName: "canvas"): HTMLCanvasElement; (tagName: "div"): HTMLDivElement; (tagName: "span"): HTMLSpanElement; } +>createElement : { (tagName: K, options?: ElementCreationOptions): HTMLElementTagNameMap[K]; (tagName: K, options?: ElementCreationOptions): HTMLElementDeprecatedTagNameMap[K]; (tagName: string, options?: ElementCreationOptions): HTMLElement; (tagName: string): HTMLElement; (tagName: "canvas"): HTMLCanvasElement; (tagName: "div"): HTMLDivElement; (tagName: "span"): HTMLSpanElement; } >tagName : "span" } diff --git a/tests/baselines/reference/restInvalidArgumentType.errors.txt b/tests/baselines/reference/restInvalidArgumentType.errors.txt index 0cc4faea557d2..7e0c852316a93 100644 --- a/tests/baselines/reference/restInvalidArgumentType.errors.txt +++ b/tests/baselines/reference/restInvalidArgumentType.errors.txt @@ -1,11 +1,5 @@ -tests/cases/compiler/restInvalidArgumentType.ts(27,13): error TS2700: Rest types may only be created from object types. -tests/cases/compiler/restInvalidArgumentType.ts(29,13): error TS2700: Rest types may only be created from object types. -tests/cases/compiler/restInvalidArgumentType.ts(30,13): error TS2700: Rest types may only be created from object types. tests/cases/compiler/restInvalidArgumentType.ts(31,13): error TS2700: Rest types may only be created from object types. -tests/cases/compiler/restInvalidArgumentType.ts(33,13): error TS2700: Rest types may only be created from object types. -tests/cases/compiler/restInvalidArgumentType.ts(36,13): error TS2700: Rest types may only be created from object types. tests/cases/compiler/restInvalidArgumentType.ts(37,13): error TS2700: Rest types may only be created from object types. -tests/cases/compiler/restInvalidArgumentType.ts(39,13): error TS2700: Rest types may only be created from object types. tests/cases/compiler/restInvalidArgumentType.ts(40,13): error TS2700: Rest types may only be created from object types. tests/cases/compiler/restInvalidArgumentType.ts(42,13): error TS2700: Rest types may only be created from object types. tests/cases/compiler/restInvalidArgumentType.ts(43,13): error TS2700: Rest types may only be created from object types. @@ -16,7 +10,7 @@ tests/cases/compiler/restInvalidArgumentType.ts(51,13): error TS2700: Rest types tests/cases/compiler/restInvalidArgumentType.ts(53,13): error TS2700: Rest types may only be created from object types. -==== tests/cases/compiler/restInvalidArgumentType.ts (16 errors) ==== +==== tests/cases/compiler/restInvalidArgumentType.ts (10 errors) ==== enum E { v1, v2 }; function f(p1: T, p2: T[]) { @@ -44,34 +38,22 @@ tests/cases/compiler/restInvalidArgumentType.ts(53,13): error TS2700: Rest types var a: any; var {...r1} = p1; // Error, generic type paramterre - ~~ -!!! error TS2700: Rest types may only be created from object types. var {...r2} = p2; // OK var {...r3} = t; // Error, generic type paramter - ~~ -!!! error TS2700: Rest types may only be created from object types. var {...r4} = i; // Error, index access - ~~ -!!! error TS2700: Rest types may only be created from object types. var {...r5} = k; // Error, index ~~ !!! error TS2700: Rest types may only be created from object types. var {...r6} = mapped_generic; // Error, generic mapped object type - ~~ -!!! error TS2700: Rest types may only be created from object types. var {...r7} = mapped; // OK, non-generic mapped type var {...r8} = union_generic; // Error, union with generic type parameter - ~~ -!!! error TS2700: Rest types may only be created from object types. var {...r9} = union_primitive; // Error, union with generic type parameter ~~ !!! error TS2700: Rest types may only be created from object types. var {...r10} = intersection_generic; // Error, intersection with generic type parameter - ~~~ -!!! error TS2700: Rest types may only be created from object types. var {...r11} = intersection_primitive; // Error, intersection with generic type parameter ~~~ !!! error TS2700: Rest types may only be created from object types. diff --git a/tests/baselines/reference/restInvalidArgumentType.types b/tests/baselines/reference/restInvalidArgumentType.types index ce59fb145f960..e04395b240756 100644 --- a/tests/baselines/reference/restInvalidArgumentType.types +++ b/tests/baselines/reference/restInvalidArgumentType.types @@ -67,19 +67,19 @@ function f(p1: T, p2: T[]) { >a : any var {...r1} = p1; // Error, generic type paramterre ->r1 : any +>r1 : T >p1 : T var {...r2} = p2; // OK ->r2 : { [n: number]: T; length: number; toString(): string; toLocaleString(): string; pop(): T; push(...items: T[]): number; concat(...items: ConcatArray[]): T[]; concat(...items: (T | ConcatArray)[]): T[]; join(separator?: string): string; reverse(): T[]; shift(): T; slice(start?: number, end?: number): T[]; sort(compareFn?: (a: T, b: T) => number): T[]; splice(start: number, deleteCount?: number): T[]; splice(start: number, deleteCount: number, ...items: T[]): T[]; unshift(...items: T[]): number; indexOf(searchElement: T, fromIndex?: number): number; lastIndexOf(searchElement: T, fromIndex?: number): number; every(callbackfn: (value: T, index: number, array: T[]) => boolean, thisArg?: any): boolean; some(callbackfn: (value: T, index: number, array: T[]) => boolean, thisArg?: any): boolean; forEach(callbackfn: (value: T, index: number, array: T[]) => void, thisArg?: any): void; map(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[]; filter(callbackfn: (value: T, index: number, array: T[]) => value is S, thisArg?: any): S[]; filter(callbackfn: (value: T, index: number, array: T[]) => any, thisArg?: any): T[]; reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T; reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T; reduce(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T; reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T; reduceRight(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; } +>r2 : T[] >p2 : T[] var {...r3} = t; // Error, generic type paramter ->r3 : any +>r3 : T >t : T var {...r4} = i; // Error, index access ->r4 : any +>r4 : T["b"] >i : T["b"] var {...r5} = k; // Error, index @@ -87,7 +87,7 @@ function f(p1: T, p2: T[]) { >k : keyof T var {...r6} = mapped_generic; // Error, generic mapped object type ->r6 : any +>r6 : { [P in keyof T]: T[P]; } >mapped_generic : { [P in keyof T]: T[P]; } var {...r7} = mapped; // OK, non-generic mapped type @@ -95,7 +95,7 @@ function f(p1: T, p2: T[]) { >mapped : { b: T["b"]; } var {...r8} = union_generic; // Error, union with generic type parameter ->r8 : any +>r8 : T | { a: number; } >union_generic : T | { a: number; } var {...r9} = union_primitive; // Error, union with generic type parameter @@ -103,7 +103,7 @@ function f(p1: T, p2: T[]) { >union_primitive : number | { a: number; } var {...r10} = intersection_generic; // Error, intersection with generic type parameter ->r10 : any +>r10 : T & { a: number; } >intersection_generic : T & { a: number; } var {...r11} = intersection_primitive; // Error, intersection with generic type parameter diff --git a/tests/baselines/reference/unusedLocalsAndObjectSpread.types b/tests/baselines/reference/unusedLocalsAndObjectSpread.types index 3fc4ae1e75195..233ea57ae6f25 100644 --- a/tests/baselines/reference/unusedLocalsAndObjectSpread.types +++ b/tests/baselines/reference/unusedLocalsAndObjectSpread.types @@ -18,7 +18,7 @@ function one() { // 'a' is declared but never used const {a, ...bar} = foo; >a : number ->bar : { b: number; } +>bar : Rest<{ a: number; b: number; }, "a"> >foo : { a: number; b: number; } console.log(bar); @@ -26,7 +26,7 @@ function one() { >console.log : (a: any) => void >console : { log(a: any): void; } >log : (a: any) => void ->bar : { b: number; } +>bar : Rest<{ a: number; b: number; }, "a"> } function two() { @@ -44,7 +44,7 @@ function two() { const {a: _, ...bar} = foo; >a : any >_ : number ->bar : { b: number; } +>bar : Rest<{ a: number; b: number; }, "a"> >foo : { a: number; b: number; } console.log(bar); @@ -52,7 +52,7 @@ function two() { >console.log : (a: any) => void >console : { log(a: any): void; } >log : (a: any) => void ->bar : { b: number; } +>bar : Rest<{ a: number; b: number; }, "a"> } function three() { @@ -69,7 +69,7 @@ function three() { // 'a' is declared but never used const {a, ...bar} = foo; // bar should be unused >a : number ->bar : { b: number; } +>bar : Rest<{ a: number; b: number; }, "a"> >foo : { a: number; b: number; } //console.log(bar); @@ -90,7 +90,7 @@ function four() { const {a: _, ...bar} = foo; // bar should be unused >a : any >_ : number ->bar : { b: number; } +>bar : Rest<{ a: number; b: number; }, "a"> >foo : { a: number; b: number; } //console.log(bar); From 0b194a2b34ded03de3294763336767e0283d24fa Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 1 Nov 2018 16:48:12 -0700 Subject: [PATCH 04/12] Define Rest as Pick> to ensure it is homomorphic --- src/lib/es5.d.ts | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/lib/es5.d.ts b/src/lib/es5.d.ts index 70e7e805899d6..98b4e3c625f7d 100644 --- a/src/lib/es5.d.ts +++ b/src/lib/es5.d.ts @@ -1416,13 +1416,6 @@ type Pick = { [P in K]: T[P]; }; -/** - * From T, omit a set of properties whose keys are in the union K - */ -type Rest = { - [P in Exclude]: T[P]; -}; - /** * Construct a type with a set of properties K of type T */ @@ -1445,6 +1438,11 @@ type Extract = T extends U ? T : never; */ type NonNullable = T extends null | undefined ? never : T; +/** + * From T, pick all properties except those in the union K + */ +type Rest = Pick>; + /** * Obtain the parameters of a function type in a tuple */ From 396642d03e51331b9d86e1270b0048fde083e8b2 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 1 Nov 2018 17:49:49 -0700 Subject: [PATCH 05/12] Only create Rest types when object and/or key type is generic --- src/compiler/checker.ts | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f8c2bc12f6392..b0bc866fdedae 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4600,15 +4600,24 @@ namespace ts { if (source.flags & TypeFlags.Union) { return mapType(source, t => getRestType(t, properties, symbol)); } - const restTypeAlias = getGlobalRestSymbol(); - if (!restTypeAlias) { - return errorType; + const omitKeyType = getUnionType(map(properties, getLiteralTypeFromPropertyName)); + if (isGenericObjectType(source) || isGenericIndexType(omitKeyType)) { + const restTypeAlias = getGlobalRestSymbol(); + return !restTypeAlias ? errorType : + omitKeyType.flags & TypeFlags.Never ? source : + getTypeAliasInstantiation(restTypeAlias, [source, omitKeyType]); } - const omitTypes = getUnionType(map(properties, getLiteralTypeFromPropertyName)); - if (omitTypes.flags & TypeFlags.Never) { - return source; + const members = createSymbolTable(); + for (const prop of getPropertiesOfType(source)) { + if (!isTypeAssignableTo(getLiteralTypeFromProperty(prop, TypeFlags.StringOrNumberLiteralOrUnique), omitKeyType) + && !(getDeclarationModifierFlagsFromSymbol(prop) & (ModifierFlags.Private | ModifierFlags.Protected)) + && isSpreadableProperty(prop)) { + members.set(prop.escapedName, getSpreadSymbol(prop)); + } } - return getTypeAliasInstantiation(restTypeAlias, [source, omitTypes]); + const stringIndexInfo = getIndexInfoOfType(source, IndexKind.String); + const numberIndexInfo = getIndexInfoOfType(source, IndexKind.Number); + return createAnonymousType(symbol, members, emptyArray, emptyArray, stringIndexInfo, numberIndexInfo); } /** Return the inferred type for a binding element */ From f55805955de50dd0068f5be3812685b5fb403402 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 1 Nov 2018 17:50:08 -0700 Subject: [PATCH 06/12] Accept new baselines --- .../asyncFunctionTempVariableScoping.types | 2 +- ...turingDoesNotElideFollowingStatement.types | 2 +- .../importHelpersInAmbientContext.types | 4 +-- .../nonPrimitiveAccessProperty.types | 2 +- .../baselines/reference/objectRest.errors.txt | 12 +++---- tests/baselines/reference/objectRest.types | 34 +++++++++---------- .../reference/objectRestAssignment.types | 8 ++--- .../baselines/reference/objectRestForOf.types | 6 ++-- .../reference/objectRestNegative.errors.txt | 4 +-- .../reference/objectRestNegative.types | 10 +++--- .../reference/objectRestParameter.symbols | 12 +++---- .../reference/objectRestParameter.types | 18 +++++----- .../reference/objectRestParameterES5.symbols | 12 +++---- .../reference/objectRestParameterES5.types | 18 +++++----- .../reference/objectRestReadonly.symbols | 4 +-- .../reference/objectRestReadonly.types | 4 +-- ...InitializerBeforeDestructuringEmit.symbols | 8 ++--- ...erInitializerBeforeDestructuringEmit.types | 8 ++--- .../reference/restInvalidArgumentType.types | 2 +- .../unusedLocalsAndObjectSpread.types | 12 +++---- 20 files changed, 91 insertions(+), 91 deletions(-) diff --git a/tests/baselines/reference/asyncFunctionTempVariableScoping.types b/tests/baselines/reference/asyncFunctionTempVariableScoping.types index cc477523cb914..30b2399490368 100644 --- a/tests/baselines/reference/asyncFunctionTempVariableScoping.types +++ b/tests/baselines/reference/asyncFunctionTempVariableScoping.types @@ -5,7 +5,7 @@ async ({ foo, bar, ...rest }) => bar(await foo); >async ({ foo, bar, ...rest }) => bar(await foo) : ({ foo, bar, ...rest }: { [x: string]: any; foo: any; bar: any; }) => Promise >foo : any >bar : any ->rest : Rest<{ [x: string]: any; foo: any; bar: any; }, "foo" | "bar"> +>rest : { [x: string]: any; } >bar(await foo) : any >bar : any >await foo : any diff --git a/tests/baselines/reference/forLoopWithDestructuringDoesNotElideFollowingStatement.types b/tests/baselines/reference/forLoopWithDestructuringDoesNotElideFollowingStatement.types index 600c4f9d71757..246c6d2e7dbcf 100644 --- a/tests/baselines/reference/forLoopWithDestructuringDoesNotElideFollowingStatement.types +++ b/tests/baselines/reference/forLoopWithDestructuringDoesNotElideFollowingStatement.types @@ -10,7 +10,7 @@ let array = [{a: 0, b: 1}] for (let { a, ...rest } of array) >a : number ->rest : Rest<{ a: number; b: number; }, "a"> +>rest : { b: number; } >array : { a: number; b: number; }[] void a diff --git a/tests/baselines/reference/importHelpersInAmbientContext.types b/tests/baselines/reference/importHelpersInAmbientContext.types index 794bdb2e41810..0c3365d7d9355 100644 --- a/tests/baselines/reference/importHelpersInAmbientContext.types +++ b/tests/baselines/reference/importHelpersInAmbientContext.types @@ -33,7 +33,7 @@ interface Foo { } export var { a, ...x } : Foo; >a : number ->x : Rest +>x : { b: string; } === tests/cases/compiler/b.ts === export {}; @@ -72,7 +72,7 @@ declare namespace N { } export var { a, ...x } : Foo; >a : number ->x : Rest +>x : { b: string; } } === tests/cases/compiler/tslib.d.ts === diff --git a/tests/baselines/reference/nonPrimitiveAccessProperty.types b/tests/baselines/reference/nonPrimitiveAccessProperty.types index 5218aa20fdafb..900df294d9b30 100644 --- a/tests/baselines/reference/nonPrimitiveAccessProperty.types +++ b/tests/baselines/reference/nonPrimitiveAccessProperty.types @@ -19,6 +19,6 @@ var { destructuring } = a; // error >a : object var { ...rest } = a; // ok ->rest : object +>rest : {} >a : object diff --git a/tests/baselines/reference/objectRest.errors.txt b/tests/baselines/reference/objectRest.errors.txt index 48d8bd3f328a1..2cee03225c301 100644 --- a/tests/baselines/reference/objectRest.errors.txt +++ b/tests/baselines/reference/objectRest.errors.txt @@ -2,9 +2,9 @@ tests/cases/conformance/types/rest/objectRest.ts(7,12): error TS2339: Property ' tests/cases/conformance/types/rest/objectRest.ts(7,20): error TS2339: Property '1' does not exist on type 'String'. tests/cases/conformance/types/rest/objectRest.ts(43,8): error TS2537: Type '{ a: number; b: string; }' has no matching index signature for type 'string'. tests/cases/conformance/types/rest/objectRest.ts(43,35): error TS2537: Type '{ a: number; b: string; }' has no matching index signature for type 'string'. -tests/cases/conformance/types/rest/objectRest.ts(43,57): error TS2403: Subsequent variable declarations must have the same type. Variable 'o' must be of type '{ a: number; b: string; }', but here has type 'Rest<{ a: number; b: string; }, string>'. -tests/cases/conformance/types/rest/objectRest.ts(44,53): error TS2322: Type 'Rest<{ a: number; b: string; }, string>' is not assignable to type '{ a: number; b: string; }'. - Property 'a' is missing in type 'Rest<{ a: number; b: string; }, string>'. +tests/cases/conformance/types/rest/objectRest.ts(43,57): error TS2403: Subsequent variable declarations must have the same type. Variable 'o' must be of type '{ a: number; b: string; }', but here has type '{}'. +tests/cases/conformance/types/rest/objectRest.ts(44,53): error TS2322: Type '{}' is not assignable to type '{ a: number; b: string; }'. + Property 'a' is missing in type '{}'. ==== tests/cases/conformance/types/rest/objectRest.ts (6 errors) ==== @@ -60,11 +60,11 @@ tests/cases/conformance/types/rest/objectRest.ts(44,53): error TS2322: Type 'Res ~~~~~~~~~ !!! error TS2537: Type '{ a: number; b: string; }' has no matching index signature for type 'string'. ~ -!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'o' must be of type '{ a: number; b: string; }', but here has type 'Rest<{ a: number; b: string; }, string>'. +!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'o' must be of type '{ a: number; b: string; }', but here has type '{}'. ({ [computed]: stillNotGreat, [computed2]: soSo, ...o } = o); ~ -!!! error TS2322: Type 'Rest<{ a: number; b: string; }, string>' is not assignable to type '{ a: number; b: string; }'. -!!! error TS2322: Property 'a' is missing in type 'Rest<{ a: number; b: string; }, string>'. +!!! error TS2322: Type '{}' is not assignable to type '{ a: number; b: string; }'. +!!! error TS2322: Property 'a' is missing in type '{}'. var noContextualType = ({ aNumber = 12, ...notEmptyObject }) => aNumber + notEmptyObject.anythingGoes; \ No newline at end of file diff --git a/tests/baselines/reference/objectRest.types b/tests/baselines/reference/objectRest.types index 6a5f823e9dd0c..dfce7e47912c0 100644 --- a/tests/baselines/reference/objectRest.types +++ b/tests/baselines/reference/objectRest.types @@ -13,32 +13,32 @@ var { ...clone } = o; var { a, ...justB } = o; >a : number ->justB : Rest<{ a: number; b: string; }, "a"> +>justB : { b: string; } >o : { a: number; b: string; } var { a, b: renamed, ...empty } = o; >a : number >b : any >renamed : string ->empty : Rest<{ a: number; b: string; }, "a" | "b"> +>empty : {} >o : { a: number; b: string; } var { ['b']: renamed, ...justA } = o; >'b' : "b" >renamed : string ->justA : Rest<{ a: number; b: string; }, "b"> +>justA : { a: number; } >o : { a: number; b: string; } var { 'b': renamed, ...justA } = o; >renamed : string ->justA : Rest<{ a: number; b: string; }, "b"> +>justA : { a: number; } >o : { a: number; b: string; } var { b: { '0': n, '1': oooo }, ...justA } = o; >b : any >n : any >oooo : any ->justA : Rest<{ a: number; b: string; }, "b"> +>justA : { a: number; } >o : { a: number; b: string; } let o2 = { c: 'terrible idea?', d: 'yes' }; @@ -52,7 +52,7 @@ let o2 = { c: 'terrible idea?', d: 'yes' }; var { d: renamed, ...d } = o2; >d : any >renamed : string ->d : Rest<{ c: string; d: string; }, "d"> +>d : { c: string; } >o2 : { c: string; d: string; } let nestedrest: { x: number, n1: { y: number, n2: { z: number, n3: { n4: number } } }, rest: number, restrest: number }; @@ -75,7 +75,7 @@ var { x, n1: { y, n2: { z, n3: { ...nr } } }, ...restrest } = nestedrest; >z : number >n3 : any >nr : { n4: number; } ->restrest : Rest<{ x: number; n1: { y: number; n2: { z: number; n3: { n4: number; }; }; }; rest: number; restrest: number; }, "x" | "n1"> +>restrest : { rest: number; restrest: number; } >nestedrest : { x: number; n1: { y: number; n2: { z: number; n3: { n4: number; }; }; }; rest: number; restrest: number; } let complex: { x: { ka, ki }, y: number }; @@ -88,10 +88,10 @@ let complex: { x: { ka, ki }, y: number }; var { x: { ka, ...nested }, y: other, ...rest } = complex; >x : any >ka : any ->nested : Rest<{ ka: any; ki: any; }, "ka"> +>nested : { ki: any; } >y : any >other : number ->rest : Rest<{ x: { ka: any; ki: any; }; y: number; }, "x" | "y"> +>rest : {} >complex : { x: { ka: any; ki: any; }; y: number; } ({x: { ka, ...nested }, y: other, ...rest} = complex); @@ -101,15 +101,15 @@ var { x: { ka, ...nested }, y: other, ...rest } = complex; >x : { ki: any; ka: any; } >{ ka, ...nested } : { ki: any; ka: any; } >ka : any ->nested : Rest<{ ka: any; ki: any; }, "ka"> +>nested : { ki: any; } >y : number >other : number ->rest : Rest<{ x: { ka: any; ki: any; }; y: number; }, "x" | "y"> +>rest : {} >complex : { x: { ka: any; ki: any; }; y: number; } var { x, ...fresh } = { x: 1, y: 2 }; >x : number ->fresh : Rest<{ x: number; y: number; }, "x"> +>fresh : { y: number; } >{ x: 1, y: 2 } : { x: number; y: number; } >x : number >1 : 1 @@ -121,7 +121,7 @@ var { x, ...fresh } = { x: 1, y: 2 }; >{ x, ...fresh } = { x: 1, y: 2 } : { x: number; y: number; } >{ x, ...fresh } : { y: number; x: number; } >x : number ->fresh : Rest<{ x: number; y: number; }, "x"> +>fresh : { y: number; } >{ x: 1, y: 2 } : { x: number; y: number; } >x : number >1 : 1 @@ -175,7 +175,7 @@ var removable = new Removable(); var { removed, ...removableRest } = removable; >removed : string ->removableRest : Rest +>removableRest : { remainder: string; } >removable : Removable var i: I = removable; @@ -184,7 +184,7 @@ var i: I = removable; var { removed, ...removableRest2 } = i; >removed : string ->removableRest2 : Rest +>removableRest2 : { m(): void; remainder: string; } >i : I let computed = 'b'; @@ -221,10 +221,10 @@ var noContextualType = ({ aNumber = 12, ...notEmptyObject }) => aNumber + notEmp >({ aNumber = 12, ...notEmptyObject }) => aNumber + notEmptyObject.anythingGoes : ({ aNumber, ...notEmptyObject }: { [x: string]: any; aNumber?: number; }) => any >aNumber : number >12 : 12 ->notEmptyObject : Rest<{ [x: string]: any; aNumber?: number; }, "aNumber"> +>notEmptyObject : { [x: string]: any; } >aNumber + notEmptyObject.anythingGoes : any >aNumber : number >notEmptyObject.anythingGoes : any ->notEmptyObject : Rest<{ [x: string]: any; aNumber?: number; }, "aNumber"> +>notEmptyObject : { [x: string]: any; } >anythingGoes : any diff --git a/tests/baselines/reference/objectRestAssignment.types b/tests/baselines/reference/objectRestAssignment.types index 04507f688cb2b..c0c84b6d5e349 100644 --- a/tests/baselines/reference/objectRestAssignment.types +++ b/tests/baselines/reference/objectRestAssignment.types @@ -52,8 +52,8 @@ var { a: [{ ...nested2 }, ...y], b: { z, ...c }, ...rest2 } = overEmit; >y : { ka: string; x: string; }[] >b : any >z : string ->c : Rest<{ z: string; ki: string; ku: string; }, "z"> ->rest2 : Rest<{ a: { ka: string; x: string; }[]; b: { z: string; ki: string; ku: string; }; ke: string; ko: string; }, "a" | "b"> +>c : { ki: string; ku: string; } +>rest2 : { ke: string; ko: string; } >overEmit : { a: { ka: string; x: string; }[]; b: { z: string; ki: string; ku: string; }; ke: string; ko: string; } ({ a: [{ ...nested2 }, ...y], b: { z, ...c }, ...rest2 } = overEmit); @@ -69,7 +69,7 @@ var { a: [{ ...nested2 }, ...y], b: { z, ...c }, ...rest2 } = overEmit; >b : { ki: string; ku: string; z: string; } >{ z, ...c } : { ki: string; ku: string; z: string; } >z : string ->c : Rest<{ z: string; ki: string; ku: string; }, "z"> ->rest2 : Rest<{ a: { ka: string; x: string; }[]; b: { z: string; ki: string; ku: string; }; ke: string; ko: string; }, "a" | "b"> +>c : { ki: string; ku: string; } +>rest2 : { ke: string; ko: string; } >overEmit : { a: { ka: string; x: string; }[]; b: { z: string; ki: string; ku: string; }; ke: string; ko: string; } diff --git a/tests/baselines/reference/objectRestForOf.types b/tests/baselines/reference/objectRestForOf.types index 107a38ecea655..30e10999bc78e 100644 --- a/tests/baselines/reference/objectRestForOf.types +++ b/tests/baselines/reference/objectRestForOf.types @@ -6,13 +6,13 @@ let array: { x: number, y: string }[]; for (let { x, ...restOf } of array) { >x : number ->restOf : Rest<{ x: number; y: string; }, "x"> +>restOf : { y: string; } >array : { x: number; y: string; }[] [x, restOf]; ->[x, restOf] : (number | Rest<{ x: number; y: string; }, "x">)[] +>[x, restOf] : (number | { y: string; })[] >x : number ->restOf : Rest<{ x: number; y: string; }, "x"> +>restOf : { y: string; } } let xx: number; >xx : number diff --git a/tests/baselines/reference/objectRestNegative.errors.txt b/tests/baselines/reference/objectRestNegative.errors.txt index 8e599f26639b4..42b25d137ef96 100644 --- a/tests/baselines/reference/objectRestNegative.errors.txt +++ b/tests/baselines/reference/objectRestNegative.errors.txt @@ -1,5 +1,5 @@ tests/cases/conformance/types/rest/objectRestNegative.ts(2,10): error TS2462: A rest element must be last in a destructuring pattern. -tests/cases/conformance/types/rest/objectRestNegative.ts(6,10): error TS2322: Type 'Rest<{ a: number; b: string; }, "b">' is not assignable to type '{ a: string; }'. +tests/cases/conformance/types/rest/objectRestNegative.ts(6,10): error TS2322: Type '{ a: number; }' is not assignable to type '{ a: string; }'. Types of property 'a' are incompatible. Type 'number' is not assignable to type 'string'. tests/cases/conformance/types/rest/objectRestNegative.ts(9,31): error TS2462: A rest element must be last in a destructuring pattern. @@ -18,7 +18,7 @@ tests/cases/conformance/types/rest/objectRestNegative.ts(17,9): error TS2701: Th let notAssignable: { a: string }; ({ b, ...notAssignable } = o); ~~~~~~~~~~~~~ -!!! error TS2322: Type 'Rest<{ a: number; b: string; }, "b">' is not assignable to type '{ a: string; }'. +!!! error TS2322: Type '{ a: number; }' is not assignable to type '{ a: string; }'. !!! error TS2322: Types of property 'a' are incompatible. !!! error TS2322: Type 'number' is not assignable to type 'string'. diff --git a/tests/baselines/reference/objectRestNegative.types b/tests/baselines/reference/objectRestNegative.types index 8287f870599fc..58ed1902f6dd4 100644 --- a/tests/baselines/reference/objectRestNegative.types +++ b/tests/baselines/reference/objectRestNegative.types @@ -8,7 +8,7 @@ let o = { a: 1, b: 'no' }; >'no' : "no" var { ...mustBeLast, a } = o; ->mustBeLast : Rest<{ a: number; b: string; }, "a"> +>mustBeLast : { b: string; } >a : number >o : { a: number; b: string; } @@ -30,24 +30,24 @@ let notAssignable: { a: string }; function stillMustBeLast({ ...mustBeLast, a }: { a: number, b: string }): void { >stillMustBeLast : ({ ...mustBeLast, a }: { a: number; b: string; }) => void ->mustBeLast : Rest<{ a: number; b: string; }, "a"> +>mustBeLast : { b: string; } >a : number >a : number >b : string } function generic(t: T) { ->generic : (t: T) => Rest +>generic : (t: T) => Pick> >x : any >y : any >t : T let { x, ...rest } = t; >x : any ->rest : Rest +>rest : Pick> >t : T return rest; ->rest : Rest +>rest : Pick> } let rest: { b: string } diff --git a/tests/baselines/reference/objectRestParameter.symbols b/tests/baselines/reference/objectRestParameter.symbols index 536689ae5679d..f629f46e8e994 100644 --- a/tests/baselines/reference/objectRestParameter.symbols +++ b/tests/baselines/reference/objectRestParameter.symbols @@ -21,9 +21,9 @@ suddenly(({ x: a, ...rest }) => rest.y); >x : Symbol(x, Decl(objectRestParameter.ts, 3, 34)) >a : Symbol(a, Decl(objectRestParameter.ts, 4, 11)) >rest : Symbol(rest, Decl(objectRestParameter.ts, 4, 17)) ->rest.y : Symbol(y) +>rest.y : Symbol(y, Decl(objectRestParameter.ts, 3, 48)) >rest : Symbol(rest, Decl(objectRestParameter.ts, 4, 17)) ->y : Symbol(y) +>y : Symbol(y, Decl(objectRestParameter.ts, 3, 48)) suddenly(({ x: { z = 12, ...nested }, ...rest } = { x: { z: 1, ka: 1 }, y: 'noo' }) => rest.y + nested.ka); >suddenly : Symbol(suddenly, Decl(objectRestParameter.ts, 1, 1)) @@ -35,12 +35,12 @@ suddenly(({ x: { z = 12, ...nested }, ...rest } = { x: { z: 1, ka: 1 }, y: 'noo' >z : Symbol(z, Decl(objectRestParameter.ts, 5, 56)) >ka : Symbol(ka, Decl(objectRestParameter.ts, 5, 62)) >y : Symbol(y, Decl(objectRestParameter.ts, 5, 71)) ->rest.y : Symbol(y) +>rest.y : Symbol(y, Decl(objectRestParameter.ts, 3, 48)) >rest : Symbol(rest, Decl(objectRestParameter.ts, 5, 37)) ->y : Symbol(y) ->nested.ka : Symbol(ka) +>y : Symbol(y, Decl(objectRestParameter.ts, 3, 48)) +>nested.ka : Symbol(ka, Decl(objectRestParameter.ts, 3, 42)) >nested : Symbol(nested, Decl(objectRestParameter.ts, 5, 24)) ->ka : Symbol(ka) +>ka : Symbol(ka, Decl(objectRestParameter.ts, 3, 42)) class C { >C : Symbol(C, Decl(objectRestParameter.ts, 5, 107)) diff --git a/tests/baselines/reference/objectRestParameter.types b/tests/baselines/reference/objectRestParameter.types index c3d1c4f01f21a..831ac9df59f9a 100644 --- a/tests/baselines/reference/objectRestParameter.types +++ b/tests/baselines/reference/objectRestParameter.types @@ -2,7 +2,7 @@ function cloneAgain({ a, ...clone }: { a: number, b: string }): void { >cloneAgain : ({ a, ...clone }: { a: number; b: string; }) => void >a : number ->clone : Rest<{ a: number; b: string; }, "a"> +>clone : { b: string; } >a : number >b : string } @@ -22,9 +22,9 @@ suddenly(({ x: a, ...rest }) => rest.y); >({ x: a, ...rest }) => rest.y : ({ x: a, ...rest }: { x: { z: any; ka: any; }; y: string; }) => string >x : any >a : { z: any; ka: any; } ->rest : Rest<{ x: { z: any; ka: any; }; y: string; }, "x"> +>rest : { y: string; } >rest.y : string ->rest : Rest<{ x: { z: any; ka: any; }; y: string; }, "x"> +>rest : { y: string; } >y : string suddenly(({ x: { z = 12, ...nested }, ...rest } = { x: { z: 1, ka: 1 }, y: 'noo' }) => rest.y + nested.ka); @@ -34,8 +34,8 @@ suddenly(({ x: { z = 12, ...nested }, ...rest } = { x: { z: 1, ka: 1 }, y: 'noo' >x : any >z : any >12 : 12 ->nested : Rest<{ z: any; ka: any; }, "z"> ->rest : Rest<{ x: { z: any; ka: any; }; y: string; }, "x"> +>nested : { ka: any; } +>rest : { y: string; } >{ x: { z: 1, ka: 1 }, y: 'noo' } : { x: { z: number; ka: number; }; y: string; } >x : { z: number; ka: number; } >{ z: 1, ka: 1 } : { z: number; ka: number; } @@ -47,10 +47,10 @@ suddenly(({ x: { z = 12, ...nested }, ...rest } = { x: { z: 1, ka: 1 }, y: 'noo' >'noo' : "noo" >rest.y + nested.ka : string >rest.y : string ->rest : Rest<{ x: { z: any; ka: any; }; y: string; }, "x"> +>rest : { y: string; } >y : string >nested.ka : any ->nested : Rest<{ z: any; ka: any; }, "z"> +>nested : { ka: any; } >ka : any class C { @@ -59,7 +59,7 @@ class C { m({ a, ...clone }: { a: number, b: string}): void { >m : ({ a, ...clone }: { a: number; b: string; }) => void >a : number ->clone : Rest<{ a: number; b: string; }, "a"> +>clone : { b: string; } >a : number >b : string @@ -68,7 +68,7 @@ class C { set p({ a, ...clone }: { a: number, b: string}) { >p : { a: number; b: string; } >a : number ->clone : Rest<{ a: number; b: string; }, "a"> +>clone : { b: string; } >a : number >b : string diff --git a/tests/baselines/reference/objectRestParameterES5.symbols b/tests/baselines/reference/objectRestParameterES5.symbols index c397e13779907..4c6b8115169b8 100644 --- a/tests/baselines/reference/objectRestParameterES5.symbols +++ b/tests/baselines/reference/objectRestParameterES5.symbols @@ -21,9 +21,9 @@ suddenly(({ x: a, ...rest }) => rest.y); >x : Symbol(x, Decl(objectRestParameterES5.ts, 3, 34)) >a : Symbol(a, Decl(objectRestParameterES5.ts, 4, 11)) >rest : Symbol(rest, Decl(objectRestParameterES5.ts, 4, 17)) ->rest.y : Symbol(y) +>rest.y : Symbol(y, Decl(objectRestParameterES5.ts, 3, 48)) >rest : Symbol(rest, Decl(objectRestParameterES5.ts, 4, 17)) ->y : Symbol(y) +>y : Symbol(y, Decl(objectRestParameterES5.ts, 3, 48)) suddenly(({ x: { z = 12, ...nested }, ...rest } = { x: { z: 1, ka: 1 }, y: 'noo' }) => rest.y + nested.ka); >suddenly : Symbol(suddenly, Decl(objectRestParameterES5.ts, 1, 1)) @@ -35,12 +35,12 @@ suddenly(({ x: { z = 12, ...nested }, ...rest } = { x: { z: 1, ka: 1 }, y: 'noo' >z : Symbol(z, Decl(objectRestParameterES5.ts, 5, 56)) >ka : Symbol(ka, Decl(objectRestParameterES5.ts, 5, 62)) >y : Symbol(y, Decl(objectRestParameterES5.ts, 5, 71)) ->rest.y : Symbol(y) +>rest.y : Symbol(y, Decl(objectRestParameterES5.ts, 3, 48)) >rest : Symbol(rest, Decl(objectRestParameterES5.ts, 5, 37)) ->y : Symbol(y) ->nested.ka : Symbol(ka) +>y : Symbol(y, Decl(objectRestParameterES5.ts, 3, 48)) +>nested.ka : Symbol(ka, Decl(objectRestParameterES5.ts, 3, 42)) >nested : Symbol(nested, Decl(objectRestParameterES5.ts, 5, 24)) ->ka : Symbol(ka) +>ka : Symbol(ka, Decl(objectRestParameterES5.ts, 3, 42)) class C { >C : Symbol(C, Decl(objectRestParameterES5.ts, 5, 107)) diff --git a/tests/baselines/reference/objectRestParameterES5.types b/tests/baselines/reference/objectRestParameterES5.types index 329f69bedcd40..1b8dd29e29ef6 100644 --- a/tests/baselines/reference/objectRestParameterES5.types +++ b/tests/baselines/reference/objectRestParameterES5.types @@ -2,7 +2,7 @@ function cloneAgain({ a, ...clone }: { a: number, b: string }): void { >cloneAgain : ({ a, ...clone }: { a: number; b: string; }) => void >a : number ->clone : Rest<{ a: number; b: string; }, "a"> +>clone : { b: string; } >a : number >b : string } @@ -22,9 +22,9 @@ suddenly(({ x: a, ...rest }) => rest.y); >({ x: a, ...rest }) => rest.y : ({ x: a, ...rest }: { x: { z: any; ka: any; }; y: string; }) => string >x : any >a : { z: any; ka: any; } ->rest : Rest<{ x: { z: any; ka: any; }; y: string; }, "x"> +>rest : { y: string; } >rest.y : string ->rest : Rest<{ x: { z: any; ka: any; }; y: string; }, "x"> +>rest : { y: string; } >y : string suddenly(({ x: { z = 12, ...nested }, ...rest } = { x: { z: 1, ka: 1 }, y: 'noo' }) => rest.y + nested.ka); @@ -34,8 +34,8 @@ suddenly(({ x: { z = 12, ...nested }, ...rest } = { x: { z: 1, ka: 1 }, y: 'noo' >x : any >z : any >12 : 12 ->nested : Rest<{ z: any; ka: any; }, "z"> ->rest : Rest<{ x: { z: any; ka: any; }; y: string; }, "x"> +>nested : { ka: any; } +>rest : { y: string; } >{ x: { z: 1, ka: 1 }, y: 'noo' } : { x: { z: number; ka: number; }; y: string; } >x : { z: number; ka: number; } >{ z: 1, ka: 1 } : { z: number; ka: number; } @@ -47,10 +47,10 @@ suddenly(({ x: { z = 12, ...nested }, ...rest } = { x: { z: 1, ka: 1 }, y: 'noo' >'noo' : "noo" >rest.y + nested.ka : string >rest.y : string ->rest : Rest<{ x: { z: any; ka: any; }; y: string; }, "x"> +>rest : { y: string; } >y : string >nested.ka : any ->nested : Rest<{ z: any; ka: any; }, "z"> +>nested : { ka: any; } >ka : any class C { @@ -59,7 +59,7 @@ class C { m({ a, ...clone }: { a: number, b: string}): void { >m : ({ a, ...clone }: { a: number; b: string; }) => void >a : number ->clone : Rest<{ a: number; b: string; }, "a"> +>clone : { b: string; } >a : number >b : string @@ -68,7 +68,7 @@ class C { set p({ a, ...clone }: { a: number, b: string}) { >p : { a: number; b: string; } >a : number ->clone : Rest<{ a: number; b: string; }, "a"> +>clone : { b: string; } >a : number >b : string diff --git a/tests/baselines/reference/objectRestReadonly.symbols b/tests/baselines/reference/objectRestReadonly.symbols index ef32c8b616a86..f2a7504e9b59e 100644 --- a/tests/baselines/reference/objectRestReadonly.symbols +++ b/tests/baselines/reference/objectRestReadonly.symbols @@ -34,7 +34,7 @@ const { foo, ...rest } = obj >obj : Symbol(obj, Decl(objectRestReadonly.ts, 7, 5)) delete rest.baz ->rest.baz : Symbol(baz) +>rest.baz : Symbol(baz, Decl(objectRestReadonly.ts, 2, 13)) >rest : Symbol(rest, Decl(objectRestReadonly.ts, 13, 12)) ->baz : Symbol(baz) +>baz : Symbol(baz, Decl(objectRestReadonly.ts, 2, 13)) diff --git a/tests/baselines/reference/objectRestReadonly.types b/tests/baselines/reference/objectRestReadonly.types index d21b5793c66cc..5f015aeb1e5f5 100644 --- a/tests/baselines/reference/objectRestReadonly.types +++ b/tests/baselines/reference/objectRestReadonly.types @@ -32,12 +32,12 @@ const obj: Readonly = { const { foo, ...rest } = obj >foo : string ->rest : Rest, "foo"> +>rest : { baz: string; quux: string; } >obj : Readonly delete rest.baz >delete rest.baz : boolean >rest.baz : string ->rest : Rest, "foo"> +>rest : { baz: string; quux: string; } >baz : string diff --git a/tests/baselines/reference/parameterInitializerBeforeDestructuringEmit.symbols b/tests/baselines/reference/parameterInitializerBeforeDestructuringEmit.symbols index e3e6dcdc9a406..857310bf87c96 100644 --- a/tests/baselines/reference/parameterInitializerBeforeDestructuringEmit.symbols +++ b/tests/baselines/reference/parameterInitializerBeforeDestructuringEmit.symbols @@ -18,9 +18,9 @@ function foobar({ bar = {}, ...opts }: Foo = {}) { "use strict"; "Some other prologue"; opts.baz(bar); ->opts.baz : Symbol(baz) +>opts.baz : Symbol(Foo.baz, Decl(parameterInitializerBeforeDestructuringEmit.ts, 1, 14)) >opts : Symbol(opts, Decl(parameterInitializerBeforeDestructuringEmit.ts, 5, 27)) ->baz : Symbol(baz) +>baz : Symbol(Foo.baz, Decl(parameterInitializerBeforeDestructuringEmit.ts, 1, 14)) >bar : Symbol(bar, Decl(parameterInitializerBeforeDestructuringEmit.ts, 5, 17)) } @@ -35,9 +35,9 @@ class C { "use strict"; "Some other prologue"; opts.baz(bar); ->opts.baz : Symbol(baz) +>opts.baz : Symbol(Foo.baz, Decl(parameterInitializerBeforeDestructuringEmit.ts, 1, 14)) >opts : Symbol(opts, Decl(parameterInitializerBeforeDestructuringEmit.ts, 12, 27)) ->baz : Symbol(baz) +>baz : Symbol(Foo.baz, Decl(parameterInitializerBeforeDestructuringEmit.ts, 1, 14)) >bar : Symbol(bar, Decl(parameterInitializerBeforeDestructuringEmit.ts, 12, 17)) } } diff --git a/tests/baselines/reference/parameterInitializerBeforeDestructuringEmit.types b/tests/baselines/reference/parameterInitializerBeforeDestructuringEmit.types index 28f71d1362b75..bbdf5580a6014 100644 --- a/tests/baselines/reference/parameterInitializerBeforeDestructuringEmit.types +++ b/tests/baselines/reference/parameterInitializerBeforeDestructuringEmit.types @@ -11,7 +11,7 @@ function foobar({ bar = {}, ...opts }: Foo = {}) { >foobar : ({ bar, ...opts }?: Foo) => void >bar : any >{} : {} ->opts : Rest +>opts : { baz?: any; } >{} : {} "use strict"; @@ -23,7 +23,7 @@ function foobar({ bar = {}, ...opts }: Foo = {}) { opts.baz(bar); >opts.baz(bar) : any >opts.baz : any ->opts : Rest +>opts : { baz?: any; } >baz : any >bar : any } @@ -34,7 +34,7 @@ class C { constructor({ bar = {}, ...opts }: Foo = {}) { >bar : any >{} : {} ->opts : Rest +>opts : { baz?: any; } >{} : {} "use strict"; @@ -46,7 +46,7 @@ class C { opts.baz(bar); >opts.baz(bar) : any >opts.baz : any ->opts : Rest +>opts : { baz?: any; } >baz : any >bar : any } diff --git a/tests/baselines/reference/restInvalidArgumentType.types b/tests/baselines/reference/restInvalidArgumentType.types index e04395b240756..54af9099c311d 100644 --- a/tests/baselines/reference/restInvalidArgumentType.types +++ b/tests/baselines/reference/restInvalidArgumentType.types @@ -71,7 +71,7 @@ function f(p1: T, p2: T[]) { >p1 : T var {...r2} = p2; // OK ->r2 : T[] +>r2 : { [n: number]: T; length: number; toString(): string; toLocaleString(): string; pop(): T; push(...items: T[]): number; concat(...items: ConcatArray[]): T[]; concat(...items: (T | ConcatArray)[]): T[]; join(separator?: string): string; reverse(): T[]; shift(): T; slice(start?: number, end?: number): T[]; sort(compareFn?: (a: T, b: T) => number): T[]; splice(start: number, deleteCount?: number): T[]; splice(start: number, deleteCount: number, ...items: T[]): T[]; unshift(...items: T[]): number; indexOf(searchElement: T, fromIndex?: number): number; lastIndexOf(searchElement: T, fromIndex?: number): number; every(callbackfn: (value: T, index: number, array: T[]) => boolean, thisArg?: any): boolean; some(callbackfn: (value: T, index: number, array: T[]) => boolean, thisArg?: any): boolean; forEach(callbackfn: (value: T, index: number, array: T[]) => void, thisArg?: any): void; map(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[]; filter(callbackfn: (value: T, index: number, array: T[]) => value is S, thisArg?: any): S[]; filter(callbackfn: (value: T, index: number, array: T[]) => any, thisArg?: any): T[]; reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T; reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T; reduce(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T; reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T; reduceRight(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; } >p2 : T[] var {...r3} = t; // Error, generic type paramter diff --git a/tests/baselines/reference/unusedLocalsAndObjectSpread.types b/tests/baselines/reference/unusedLocalsAndObjectSpread.types index 233ea57ae6f25..3fc4ae1e75195 100644 --- a/tests/baselines/reference/unusedLocalsAndObjectSpread.types +++ b/tests/baselines/reference/unusedLocalsAndObjectSpread.types @@ -18,7 +18,7 @@ function one() { // 'a' is declared but never used const {a, ...bar} = foo; >a : number ->bar : Rest<{ a: number; b: number; }, "a"> +>bar : { b: number; } >foo : { a: number; b: number; } console.log(bar); @@ -26,7 +26,7 @@ function one() { >console.log : (a: any) => void >console : { log(a: any): void; } >log : (a: any) => void ->bar : Rest<{ a: number; b: number; }, "a"> +>bar : { b: number; } } function two() { @@ -44,7 +44,7 @@ function two() { const {a: _, ...bar} = foo; >a : any >_ : number ->bar : Rest<{ a: number; b: number; }, "a"> +>bar : { b: number; } >foo : { a: number; b: number; } console.log(bar); @@ -52,7 +52,7 @@ function two() { >console.log : (a: any) => void >console : { log(a: any): void; } >log : (a: any) => void ->bar : Rest<{ a: number; b: number; }, "a"> +>bar : { b: number; } } function three() { @@ -69,7 +69,7 @@ function three() { // 'a' is declared but never used const {a, ...bar} = foo; // bar should be unused >a : number ->bar : Rest<{ a: number; b: number; }, "a"> +>bar : { b: number; } >foo : { a: number; b: number; } //console.log(bar); @@ -90,7 +90,7 @@ function four() { const {a: _, ...bar} = foo; // bar should be unused >a : any >_ : number ->bar : Rest<{ a: number; b: number; }, "a"> +>bar : { b: number; } >foo : { a: number; b: number; } //console.log(bar); From 9fd7d0a5f4cbe901c87ac04c32489db69c654f3e Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 2 Nov 2018 06:40:26 -0700 Subject: [PATCH 07/12] Remove Rest and use Pick> instead --- src/compiler/checker.ts | 30 ++++++++++++++++++++---------- src/lib/es5.d.ts | 5 ----- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index b0bc866fdedae..e0f40cd2606b0 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -517,7 +517,8 @@ namespace ts { let deferredGlobalTemplateStringsArrayType: ObjectType; let deferredGlobalImportMetaType: ObjectType; let deferredGlobalExtractSymbol: Symbol; - let deferredGlobalRestSymbol: Symbol; + let deferredGlobalExcludeSymbol: Symbol; + let deferredGlobalPickSymbol: Symbol; const allPotentiallyUnusedIdentifiers = createMap(); // key is file name @@ -4602,10 +4603,16 @@ namespace ts { } const omitKeyType = getUnionType(map(properties, getLiteralTypeFromPropertyName)); if (isGenericObjectType(source) || isGenericIndexType(omitKeyType)) { - const restTypeAlias = getGlobalRestSymbol(); - return !restTypeAlias ? errorType : - omitKeyType.flags & TypeFlags.Never ? source : - getTypeAliasInstantiation(restTypeAlias, [source, omitKeyType]); + if (omitKeyType.flags & TypeFlags.Never) { + return source; + } + const pickTypeAlias = getGlobalPickSymbol(); + const excludeTypeAlias = getGlobalExcludeSymbol(); + if (!pickTypeAlias || !excludeTypeAlias) { + return errorType; + } + const pickKeys = getTypeAliasInstantiation(excludeTypeAlias, [getIndexType(source), omitKeyType]); + return getTypeAliasInstantiation(pickTypeAlias, [source, pickKeys]); } const members = createSymbolTable(); for (const prop of getPropertiesOfType(source)) { @@ -8640,8 +8647,12 @@ namespace ts { return deferredGlobalExtractSymbol || (deferredGlobalExtractSymbol = getGlobalSymbol("Extract" as __String, SymbolFlags.TypeAlias, Diagnostics.Cannot_find_global_type_0)!); // TODO: GH#18217 } - function getGlobalRestSymbol(): Symbol { - return deferredGlobalRestSymbol || (deferredGlobalRestSymbol = getGlobalSymbol("Rest" as __String, SymbolFlags.TypeAlias, Diagnostics.Cannot_find_global_type_0)!); // TODO: GH#18217 + function getGlobalExcludeSymbol(): Symbol { + return deferredGlobalExcludeSymbol || (deferredGlobalExcludeSymbol = getGlobalSymbol("Exclude" as __String, SymbolFlags.TypeAlias, Diagnostics.Cannot_find_global_type_0)!); // TODO: GH#18217 + } + + function getGlobalPickSymbol(): Symbol { + return deferredGlobalPickSymbol || (deferredGlobalPickSymbol = getGlobalSymbol("Pick" as __String, SymbolFlags.TypeAlias, Diagnostics.Cannot_find_global_type_0)!); // TODO: GH#18217 } /** @@ -9227,9 +9238,8 @@ namespace ts { } function getLiteralTypeFromPropertyName(name: PropertyName) { - return isComputedPropertyName(name) ? checkComputedPropertyName(name) : - isIdentifier(name) ? getLiteralType(unescapeLeadingUnderscores(name.escapedText)) : - checkExpression(name); + return isIdentifier(name) ? getLiteralType(unescapeLeadingUnderscores(name.escapedText)) : + getRegularTypeOfLiteralType(isComputedPropertyName(name) ? checkComputedPropertyName(name) : checkExpression(name)); } function getLiteralTypeFromProperty(prop: Symbol, include: TypeFlags) { diff --git a/src/lib/es5.d.ts b/src/lib/es5.d.ts index 98b4e3c625f7d..c8e99f0d1dbaf 100644 --- a/src/lib/es5.d.ts +++ b/src/lib/es5.d.ts @@ -1438,11 +1438,6 @@ type Extract = T extends U ? T : never; */ type NonNullable = T extends null | undefined ? never : T; -/** - * From T, pick all properties except those in the union K - */ -type Rest = Pick>; - /** * Obtain the parameters of a function type in a tuple */ From 9daf69de4c676aac0eaba84a1c8a2234fac33e79 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 2 Nov 2018 06:40:33 -0700 Subject: [PATCH 08/12] Accept new baselines --- .../reference/expressionTypeNodeShouldError.types | 12 ++++++------ .../reference/intersectionsOfLargeUnions.types | 6 +++--- .../reference/intersectionsOfLargeUnions2.types | 6 +++--- .../reference/modularizeLibrary_Dom.iterable.types | 4 ++-- .../reference/parserOverloadOnConstants1.types | 8 ++++---- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/tests/baselines/reference/expressionTypeNodeShouldError.types b/tests/baselines/reference/expressionTypeNodeShouldError.types index 90707d4db507b..45c12d7c8ffe9 100644 --- a/tests/baselines/reference/expressionTypeNodeShouldError.types +++ b/tests/baselines/reference/expressionTypeNodeShouldError.types @@ -31,9 +31,9 @@ class C { const nodes = document.getElementsByTagName("li"); >nodes : HTMLCollectionOf >document.getElementsByTagName("li") : HTMLCollectionOf ->document.getElementsByTagName : { (qualifiedName: K): HTMLCollectionOf; (qualifiedName: K): HTMLCollectionOf; (qualifiedName: string): HTMLCollectionOf; } +>document.getElementsByTagName : { (qualifiedName: K): HTMLCollectionOf; (qualifiedName: K): HTMLCollectionOf; (qualifiedName: string): HTMLCollectionOf; } >document : Document ->getElementsByTagName : { (qualifiedName: K): HTMLCollectionOf; (qualifiedName: K): HTMLCollectionOf; (qualifiedName: string): HTMLCollectionOf; } +>getElementsByTagName : { (qualifiedName: K): HTMLCollectionOf; (qualifiedName: K): HTMLCollectionOf; (qualifiedName: string): HTMLCollectionOf; } >"li" : "li" type ItemType = "".typeof(nodes.item(0)); @@ -72,9 +72,9 @@ class C2 { const nodes2 = document.getElementsByTagName("li"); >nodes2 : HTMLCollectionOf >document.getElementsByTagName("li") : HTMLCollectionOf ->document.getElementsByTagName : { (qualifiedName: K): HTMLCollectionOf; (qualifiedName: K): HTMLCollectionOf; (qualifiedName: string): HTMLCollectionOf; } +>document.getElementsByTagName : { (qualifiedName: K): HTMLCollectionOf; (qualifiedName: K): HTMLCollectionOf; (qualifiedName: string): HTMLCollectionOf; } >document : Document ->getElementsByTagName : { (qualifiedName: K): HTMLCollectionOf; (qualifiedName: K): HTMLCollectionOf; (qualifiedName: string): HTMLCollectionOf; } +>getElementsByTagName : { (qualifiedName: K): HTMLCollectionOf; (qualifiedName: K): HTMLCollectionOf; (qualifiedName: string): HTMLCollectionOf; } >"li" : "li" type ItemType2 = 4..typeof(nodes.item(0)); @@ -114,9 +114,9 @@ class C3 { const nodes3 = document.getElementsByTagName("li"); >nodes3 : HTMLCollectionOf >document.getElementsByTagName("li") : HTMLCollectionOf ->document.getElementsByTagName : { (qualifiedName: K): HTMLCollectionOf; (qualifiedName: K): HTMLCollectionOf; (qualifiedName: string): HTMLCollectionOf; } +>document.getElementsByTagName : { (qualifiedName: K): HTMLCollectionOf; (qualifiedName: K): HTMLCollectionOf; (qualifiedName: string): HTMLCollectionOf; } >document : Document ->getElementsByTagName : { (qualifiedName: K): HTMLCollectionOf; (qualifiedName: K): HTMLCollectionOf; (qualifiedName: string): HTMLCollectionOf; } +>getElementsByTagName : { (qualifiedName: K): HTMLCollectionOf; (qualifiedName: K): HTMLCollectionOf; (qualifiedName: string): HTMLCollectionOf; } >"li" : "li" type ItemType3 = true.typeof(nodes.item(0)); diff --git a/tests/baselines/reference/intersectionsOfLargeUnions.types b/tests/baselines/reference/intersectionsOfLargeUnions.types index 26f93ac79db08..06d01c0c6b2df 100644 --- a/tests/baselines/reference/intersectionsOfLargeUnions.types +++ b/tests/baselines/reference/intersectionsOfLargeUnions.types @@ -24,7 +24,7 @@ export function assertIsElement(node: Node | null): node is Element { } export function assertNodeTagName< ->assertNodeTagName : (node: Node | null, tagName: T) => node is U +>assertNodeTagName : (node: Node | null, tagName: T) => node is U T extends keyof ElementTagNameMap, U extends ElementTagNameMap[T]>(node: Node | null, tagName: T): node is U { @@ -56,7 +56,7 @@ export function assertNodeTagName< } export function assertNodeProperty< ->assertNodeProperty : (node: Node | null, tagName: T, prop: P, value: V) => void +>assertNodeProperty : (node: Node | null, tagName: T, prop: P, value: V) => void T extends keyof ElementTagNameMap, P extends keyof ElementTagNameMap[T], @@ -69,7 +69,7 @@ export function assertNodeProperty< if (assertNodeTagName(node, tagName)) { >assertNodeTagName(node, tagName) : boolean ->assertNodeTagName : (node: Node | null, tagName: T) => node is U +>assertNodeTagName : (node: Node | null, tagName: T) => node is U >node : Node | null >tagName : T diff --git a/tests/baselines/reference/intersectionsOfLargeUnions2.types b/tests/baselines/reference/intersectionsOfLargeUnions2.types index 277806ae314aa..82160fb235e18 100644 --- a/tests/baselines/reference/intersectionsOfLargeUnions2.types +++ b/tests/baselines/reference/intersectionsOfLargeUnions2.types @@ -38,7 +38,7 @@ export function assertIsElement(node: Node | null): node is Element { } export function assertNodeTagName< ->assertNodeTagName : (node: Node | null, tagName: T) => node is U +>assertNodeTagName : (node: Node | null, tagName: T) => node is U T extends keyof ElementTagNameMap, U extends ElementTagNameMap[T]>(node: Node | null, tagName: T): node is U { @@ -70,7 +70,7 @@ export function assertNodeTagName< } export function assertNodeProperty< ->assertNodeProperty : (node: Node | null, tagName: T, prop: P, value: V) => void +>assertNodeProperty : (node: Node | null, tagName: T, prop: P, value: V) => void T extends keyof ElementTagNameMap, P extends keyof ElementTagNameMap[T], @@ -83,7 +83,7 @@ export function assertNodeProperty< if (assertNodeTagName(node, tagName)) { >assertNodeTagName(node, tagName) : boolean ->assertNodeTagName : (node: Node | null, tagName: T) => node is U +>assertNodeTagName : (node: Node | null, tagName: T) => node is U >node : Node | null >tagName : T diff --git a/tests/baselines/reference/modularizeLibrary_Dom.iterable.types b/tests/baselines/reference/modularizeLibrary_Dom.iterable.types index 70c6a6cb5b91f..e2ba3e7a30086 100644 --- a/tests/baselines/reference/modularizeLibrary_Dom.iterable.types +++ b/tests/baselines/reference/modularizeLibrary_Dom.iterable.types @@ -2,9 +2,9 @@ for (const element of document.getElementsByTagName("a")) { >element : HTMLAnchorElement >document.getElementsByTagName("a") : HTMLCollectionOf ->document.getElementsByTagName : { (qualifiedName: K): HTMLCollectionOf; (qualifiedName: K): HTMLCollectionOf; (qualifiedName: string): HTMLCollectionOf; } +>document.getElementsByTagName : { (qualifiedName: K): HTMLCollectionOf; (qualifiedName: K): HTMLCollectionOf; (qualifiedName: string): HTMLCollectionOf; } >document : Document ->getElementsByTagName : { (qualifiedName: K): HTMLCollectionOf; (qualifiedName: K): HTMLCollectionOf; (qualifiedName: string): HTMLCollectionOf; } +>getElementsByTagName : { (qualifiedName: K): HTMLCollectionOf; (qualifiedName: K): HTMLCollectionOf; (qualifiedName: string): HTMLCollectionOf; } >"a" : "a" element.href; diff --git a/tests/baselines/reference/parserOverloadOnConstants1.types b/tests/baselines/reference/parserOverloadOnConstants1.types index 2a865af7ba7e4..6cac9a704a9f6 100644 --- a/tests/baselines/reference/parserOverloadOnConstants1.types +++ b/tests/baselines/reference/parserOverloadOnConstants1.types @@ -1,18 +1,18 @@ === tests/cases/conformance/parser/ecmascript5/parserOverloadOnConstants1.ts === interface Document { createElement(tagName: string): HTMLElement; ->createElement : { (tagName: K, options?: ElementCreationOptions): HTMLElementTagNameMap[K]; (tagName: K, options?: ElementCreationOptions): HTMLElementDeprecatedTagNameMap[K]; (tagName: string, options?: ElementCreationOptions): HTMLElement; (tagName: string): HTMLElement; (tagName: "canvas"): HTMLCanvasElement; (tagName: "div"): HTMLDivElement; (tagName: "span"): HTMLSpanElement; } +>createElement : { (tagName: K, options?: ElementCreationOptions): HTMLElementTagNameMap[K]; (tagName: K, options?: ElementCreationOptions): HTMLElementDeprecatedTagNameMap[K]; (tagName: string, options?: ElementCreationOptions): HTMLElement; (tagName: string): HTMLElement; (tagName: "canvas"): HTMLCanvasElement; (tagName: "div"): HTMLDivElement; (tagName: "span"): HTMLSpanElement; } >tagName : string createElement(tagName: 'canvas'): HTMLCanvasElement; ->createElement : { (tagName: K, options?: ElementCreationOptions): HTMLElementTagNameMap[K]; (tagName: K, options?: ElementCreationOptions): HTMLElementDeprecatedTagNameMap[K]; (tagName: string, options?: ElementCreationOptions): HTMLElement; (tagName: string): HTMLElement; (tagName: "canvas"): HTMLCanvasElement; (tagName: "div"): HTMLDivElement; (tagName: "span"): HTMLSpanElement; } +>createElement : { (tagName: K, options?: ElementCreationOptions): HTMLElementTagNameMap[K]; (tagName: K, options?: ElementCreationOptions): HTMLElementDeprecatedTagNameMap[K]; (tagName: string, options?: ElementCreationOptions): HTMLElement; (tagName: string): HTMLElement; (tagName: "canvas"): HTMLCanvasElement; (tagName: "div"): HTMLDivElement; (tagName: "span"): HTMLSpanElement; } >tagName : "canvas" createElement(tagName: 'div'): HTMLDivElement; ->createElement : { (tagName: K, options?: ElementCreationOptions): HTMLElementTagNameMap[K]; (tagName: K, options?: ElementCreationOptions): HTMLElementDeprecatedTagNameMap[K]; (tagName: string, options?: ElementCreationOptions): HTMLElement; (tagName: string): HTMLElement; (tagName: "canvas"): HTMLCanvasElement; (tagName: "div"): HTMLDivElement; (tagName: "span"): HTMLSpanElement; } +>createElement : { (tagName: K, options?: ElementCreationOptions): HTMLElementTagNameMap[K]; (tagName: K, options?: ElementCreationOptions): HTMLElementDeprecatedTagNameMap[K]; (tagName: string, options?: ElementCreationOptions): HTMLElement; (tagName: string): HTMLElement; (tagName: "canvas"): HTMLCanvasElement; (tagName: "div"): HTMLDivElement; (tagName: "span"): HTMLSpanElement; } >tagName : "div" createElement(tagName: 'span'): HTMLSpanElement; ->createElement : { (tagName: K, options?: ElementCreationOptions): HTMLElementTagNameMap[K]; (tagName: K, options?: ElementCreationOptions): HTMLElementDeprecatedTagNameMap[K]; (tagName: string, options?: ElementCreationOptions): HTMLElement; (tagName: string): HTMLElement; (tagName: "canvas"): HTMLCanvasElement; (tagName: "div"): HTMLDivElement; (tagName: "span"): HTMLSpanElement; } +>createElement : { (tagName: K, options?: ElementCreationOptions): HTMLElementTagNameMap[K]; (tagName: K, options?: ElementCreationOptions): HTMLElementDeprecatedTagNameMap[K]; (tagName: string, options?: ElementCreationOptions): HTMLElement; (tagName: string): HTMLElement; (tagName: "canvas"): HTMLCanvasElement; (tagName: "div"): HTMLDivElement; (tagName: "span"): HTMLSpanElement; } >tagName : "span" } From abebf15af8647526e3108662d306a49415d21269 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 2 Nov 2018 07:53:25 -0700 Subject: [PATCH 09/12] Ensure '{ [key]: x } = obj' for generic key is the same as 'x = obj[key]' --- src/compiler/checker.ts | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index e0f40cd2606b0..465e4c0ecb61c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4667,12 +4667,8 @@ namespace ts { else { // Use explicitly specified property name ({ p: xxx } form), or otherwise the implied name ({ p } form) const name = declaration.propertyName || declaration.name; - const exprType = isComputedPropertyName(name) - ? checkComputedPropertyName(name) - : isIdentifier(name) - ? getLiteralType(unescapeLeadingUnderscores(name.escapedText)) - : checkExpression(name); - const declaredType = checkIndexedAccessIndexType(getIndexedAccessType(getApparentType(parentType), exprType, name), name); + const exprType = getLiteralTypeFromPropertyName(name); + const declaredType = checkIndexedAccessIndexType(getIndexedAccessType(parentType, exprType, name), name); type = getFlowTypeOfReference(declaration, getConstraintForLocation(declaredType, declaration.name)); } } @@ -9528,7 +9524,7 @@ namespace ts { // object type. Note that for a generic T and a non-generic K, we eagerly resolve T[K] if it originates in // an expression. This is to preserve backwards compatibility. For example, an element access 'this["foo"]' // has always been resolved eagerly using the constraint type of 'this' at the given location. - if (isGenericIndexType(indexType) || !(accessNode && accessNode.kind === SyntaxKind.ElementAccessExpression) && isGenericObjectType(objectType)) { + if (isGenericIndexType(indexType) || !(accessNode && accessNode.kind !== SyntaxKind.IndexedAccessType) && isGenericObjectType(objectType)) { if (objectType.flags & TypeFlags.AnyOrUnknown) { return objectType; } From bcc1d2a8cd41ca54591db5ef2f095cd01925e476 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 2 Nov 2018 07:53:48 -0700 Subject: [PATCH 10/12] Accept new baselines --- .../definiteAssignmentOfDestructuredVariable.types | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/baselines/reference/definiteAssignmentOfDestructuredVariable.types b/tests/baselines/reference/definiteAssignmentOfDestructuredVariable.types index fb40a9b492e6f..96d632736dd84 100644 --- a/tests/baselines/reference/definiteAssignmentOfDestructuredVariable.types +++ b/tests/baselines/reference/definiteAssignmentOfDestructuredVariable.types @@ -18,20 +18,20 @@ class C { >method : () => void let { a, b } = this.foo; ->a : { [P in keyof T]: T[P]; }["a"] ->b : { [P in keyof T]: T[P]; }["b"] +>a : T["a"] +>b : T["b"] >this.foo : { [P in keyof T]: T[P]; } >this : this >foo : { [P in keyof T]: T[P]; } !(a && b); >!(a && b) : false ->(a && b) : { [P in keyof T]: T[P]; }["b"] ->a && b : { [P in keyof T]: T[P]; }["b"] ->a : { [P in keyof T]: T[P]; }["a"] ->b : { [P in keyof T]: T[P]; }["b"] +>(a && b) : T["b"] +>a && b : T["b"] +>a : T["a"] +>b : T["b"] a; ->a : { [P in keyof T]: T[P]; }["a"] +>a : T["a"] } } From 48c0aedf54eba2f048038bb4d804549c70e28396 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 2 Nov 2018 08:20:06 -0700 Subject: [PATCH 11/12] Add tests --- .../types/rest/genericObjectRest.ts | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 tests/cases/conformance/types/rest/genericObjectRest.ts diff --git a/tests/cases/conformance/types/rest/genericObjectRest.ts b/tests/cases/conformance/types/rest/genericObjectRest.ts new file mode 100644 index 0000000000000..18649db64158c --- /dev/null +++ b/tests/cases/conformance/types/rest/genericObjectRest.ts @@ -0,0 +1,30 @@ +// @strict: true +// @target: es2015 + +const a = 'a'; + +function f1(obj: T) { + let { ...r0 } = obj; + let { a: a1, ...r1 } = obj; + let { a: a2, b: b2, ...r2 } = obj; + let { 'a': a3, ...r3 } = obj; + let { ['a']: a4, ...r4 } = obj; + let { [a]: a5, ...r5 } = obj; +} + +const sa = Symbol(); +const sb = Symbol(); + +function f2(obj: T) { + let { [sa]: a1, [sb]: b1, ...r1 } = obj; +} + +function f3(obj: T, k1: K1, k2: K2) { + let { [k1]: a1, [k2]: a2, ...r1 } = obj; +} + +type Item = { a: string, b: number, c: boolean }; + +function f4(obj: Item, k1: K1, k2: K2) { + let { [k1]: a1, [k2]: a2, ...r1 } = obj; +} From 00c5071be6a78de74c63d9b00c107ca09e7ce849 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 2 Nov 2018 08:20:13 -0700 Subject: [PATCH 12/12] Accept new baselines --- .../baselines/reference/genericObjectRest.js | 61 +++++++++ .../reference/genericObjectRest.symbols | 126 ++++++++++++++++++ .../reference/genericObjectRest.types | 110 +++++++++++++++ 3 files changed, 297 insertions(+) create mode 100644 tests/baselines/reference/genericObjectRest.js create mode 100644 tests/baselines/reference/genericObjectRest.symbols create mode 100644 tests/baselines/reference/genericObjectRest.types diff --git a/tests/baselines/reference/genericObjectRest.js b/tests/baselines/reference/genericObjectRest.js new file mode 100644 index 0000000000000..33de97a3d5f6a --- /dev/null +++ b/tests/baselines/reference/genericObjectRest.js @@ -0,0 +1,61 @@ +//// [genericObjectRest.ts] +const a = 'a'; + +function f1(obj: T) { + let { ...r0 } = obj; + let { a: a1, ...r1 } = obj; + let { a: a2, b: b2, ...r2 } = obj; + let { 'a': a3, ...r3 } = obj; + let { ['a']: a4, ...r4 } = obj; + let { [a]: a5, ...r5 } = obj; +} + +const sa = Symbol(); +const sb = Symbol(); + +function f2(obj: T) { + let { [sa]: a1, [sb]: b1, ...r1 } = obj; +} + +function f3(obj: T, k1: K1, k2: K2) { + let { [k1]: a1, [k2]: a2, ...r1 } = obj; +} + +type Item = { a: string, b: number, c: boolean }; + +function f4(obj: Item, k1: K1, k2: K2) { + let { [k1]: a1, [k2]: a2, ...r1 } = obj; +} + + +//// [genericObjectRest.js] +"use strict"; +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) + t[p[i]] = s[p[i]]; + return t; +}; +const a = 'a'; +function f1(obj) { + let r0 = __rest(obj, []); + let { a: a1 } = obj, r1 = __rest(obj, ["a"]); + let { a: a2, b: b2 } = obj, r2 = __rest(obj, ["a", "b"]); + let { 'a': a3 } = obj, r3 = __rest(obj, ['a']); + let { ['a']: a4 } = obj, r4 = __rest(obj, ['a']); + let _a = a, a5 = obj[_a], r5 = __rest(obj, [typeof _a === "symbol" ? _a : _a + ""]); +} +const sa = Symbol(); +const sb = Symbol(); +function f2(obj) { + let _a = sa, a1 = obj[_a], _b = sb, b1 = obj[_b], r1 = __rest(obj, [typeof _a === "symbol" ? _a : _a + "", typeof _b === "symbol" ? _b : _b + ""]); +} +function f3(obj, k1, k2) { + let _a = k1, a1 = obj[_a], _b = k2, a2 = obj[_b], r1 = __rest(obj, [typeof _a === "symbol" ? _a : _a + "", typeof _b === "symbol" ? _b : _b + ""]); +} +function f4(obj, k1, k2) { + let _a = k1, a1 = obj[_a], _b = k2, a2 = obj[_b], r1 = __rest(obj, [typeof _a === "symbol" ? _a : _a + "", typeof _b === "symbol" ? _b : _b + ""]); +} diff --git a/tests/baselines/reference/genericObjectRest.symbols b/tests/baselines/reference/genericObjectRest.symbols new file mode 100644 index 0000000000000..1bec7d4b1ed92 --- /dev/null +++ b/tests/baselines/reference/genericObjectRest.symbols @@ -0,0 +1,126 @@ +=== tests/cases/conformance/types/rest/genericObjectRest.ts === +const a = 'a'; +>a : Symbol(a, Decl(genericObjectRest.ts, 0, 5)) + +function f1(obj: T) { +>f1 : Symbol(f1, Decl(genericObjectRest.ts, 0, 14)) +>T : Symbol(T, Decl(genericObjectRest.ts, 2, 12)) +>a : Symbol(a, Decl(genericObjectRest.ts, 2, 23)) +>b : Symbol(b, Decl(genericObjectRest.ts, 2, 34)) +>obj : Symbol(obj, Decl(genericObjectRest.ts, 2, 48)) +>T : Symbol(T, Decl(genericObjectRest.ts, 2, 12)) + + let { ...r0 } = obj; +>r0 : Symbol(r0, Decl(genericObjectRest.ts, 3, 9)) +>obj : Symbol(obj, Decl(genericObjectRest.ts, 2, 48)) + + let { a: a1, ...r1 } = obj; +>a : Symbol(a, Decl(genericObjectRest.ts, 2, 23)) +>a1 : Symbol(a1, Decl(genericObjectRest.ts, 4, 9)) +>r1 : Symbol(r1, Decl(genericObjectRest.ts, 4, 16)) +>obj : Symbol(obj, Decl(genericObjectRest.ts, 2, 48)) + + let { a: a2, b: b2, ...r2 } = obj; +>a : Symbol(a, Decl(genericObjectRest.ts, 2, 23)) +>a2 : Symbol(a2, Decl(genericObjectRest.ts, 5, 9)) +>b : Symbol(b, Decl(genericObjectRest.ts, 2, 34)) +>b2 : Symbol(b2, Decl(genericObjectRest.ts, 5, 16)) +>r2 : Symbol(r2, Decl(genericObjectRest.ts, 5, 23)) +>obj : Symbol(obj, Decl(genericObjectRest.ts, 2, 48)) + + let { 'a': a3, ...r3 } = obj; +>a3 : Symbol(a3, Decl(genericObjectRest.ts, 6, 9)) +>r3 : Symbol(r3, Decl(genericObjectRest.ts, 6, 18)) +>obj : Symbol(obj, Decl(genericObjectRest.ts, 2, 48)) + + let { ['a']: a4, ...r4 } = obj; +>'a' : Symbol(a4, Decl(genericObjectRest.ts, 7, 9)) +>a4 : Symbol(a4, Decl(genericObjectRest.ts, 7, 9)) +>r4 : Symbol(r4, Decl(genericObjectRest.ts, 7, 20)) +>obj : Symbol(obj, Decl(genericObjectRest.ts, 2, 48)) + + let { [a]: a5, ...r5 } = obj; +>a : Symbol(a, Decl(genericObjectRest.ts, 0, 5)) +>a5 : Symbol(a5, Decl(genericObjectRest.ts, 8, 9)) +>r5 : Symbol(r5, Decl(genericObjectRest.ts, 8, 18)) +>obj : Symbol(obj, Decl(genericObjectRest.ts, 2, 48)) +} + +const sa = Symbol(); +>sa : Symbol(sa, Decl(genericObjectRest.ts, 11, 5)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + +const sb = Symbol(); +>sb : Symbol(sb, Decl(genericObjectRest.ts, 12, 5)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + +function f2(obj: T) { +>f2 : Symbol(f2, Decl(genericObjectRest.ts, 12, 20)) +>T : Symbol(T, Decl(genericObjectRest.ts, 14, 12)) +>[sa] : Symbol([sa], Decl(genericObjectRest.ts, 14, 23)) +>sa : Symbol(sa, Decl(genericObjectRest.ts, 11, 5)) +>[sb] : Symbol([sb], Decl(genericObjectRest.ts, 14, 37)) +>sb : Symbol(sb, Decl(genericObjectRest.ts, 12, 5)) +>obj : Symbol(obj, Decl(genericObjectRest.ts, 14, 54)) +>T : Symbol(T, Decl(genericObjectRest.ts, 14, 12)) + + let { [sa]: a1, [sb]: b1, ...r1 } = obj; +>sa : Symbol(sa, Decl(genericObjectRest.ts, 11, 5)) +>a1 : Symbol(a1, Decl(genericObjectRest.ts, 15, 9)) +>sb : Symbol(sb, Decl(genericObjectRest.ts, 12, 5)) +>b1 : Symbol(b1, Decl(genericObjectRest.ts, 15, 19)) +>r1 : Symbol(r1, Decl(genericObjectRest.ts, 15, 29)) +>obj : Symbol(obj, Decl(genericObjectRest.ts, 14, 54)) +} + +function f3(obj: T, k1: K1, k2: K2) { +>f3 : Symbol(f3, Decl(genericObjectRest.ts, 16, 1)) +>T : Symbol(T, Decl(genericObjectRest.ts, 18, 12)) +>K1 : Symbol(K1, Decl(genericObjectRest.ts, 18, 14)) +>T : Symbol(T, Decl(genericObjectRest.ts, 18, 12)) +>K2 : Symbol(K2, Decl(genericObjectRest.ts, 18, 34)) +>T : Symbol(T, Decl(genericObjectRest.ts, 18, 12)) +>obj : Symbol(obj, Decl(genericObjectRest.ts, 18, 55)) +>T : Symbol(T, Decl(genericObjectRest.ts, 18, 12)) +>k1 : Symbol(k1, Decl(genericObjectRest.ts, 18, 62)) +>K1 : Symbol(K1, Decl(genericObjectRest.ts, 18, 14)) +>k2 : Symbol(k2, Decl(genericObjectRest.ts, 18, 70)) +>K2 : Symbol(K2, Decl(genericObjectRest.ts, 18, 34)) + + let { [k1]: a1, [k2]: a2, ...r1 } = obj; +>k1 : Symbol(k1, Decl(genericObjectRest.ts, 18, 62)) +>a1 : Symbol(a1, Decl(genericObjectRest.ts, 19, 9)) +>k2 : Symbol(k2, Decl(genericObjectRest.ts, 18, 70)) +>a2 : Symbol(a2, Decl(genericObjectRest.ts, 19, 19)) +>r1 : Symbol(r1, Decl(genericObjectRest.ts, 19, 29)) +>obj : Symbol(obj, Decl(genericObjectRest.ts, 18, 55)) +} + +type Item = { a: string, b: number, c: boolean }; +>Item : Symbol(Item, Decl(genericObjectRest.ts, 20, 1)) +>a : Symbol(a, Decl(genericObjectRest.ts, 22, 13)) +>b : Symbol(b, Decl(genericObjectRest.ts, 22, 24)) +>c : Symbol(c, Decl(genericObjectRest.ts, 22, 35)) + +function f4(obj: Item, k1: K1, k2: K2) { +>f4 : Symbol(f4, Decl(genericObjectRest.ts, 22, 49)) +>K1 : Symbol(K1, Decl(genericObjectRest.ts, 24, 12)) +>Item : Symbol(Item, Decl(genericObjectRest.ts, 20, 1)) +>K2 : Symbol(K2, Decl(genericObjectRest.ts, 24, 34)) +>Item : Symbol(Item, Decl(genericObjectRest.ts, 20, 1)) +>obj : Symbol(obj, Decl(genericObjectRest.ts, 24, 58)) +>Item : Symbol(Item, Decl(genericObjectRest.ts, 20, 1)) +>k1 : Symbol(k1, Decl(genericObjectRest.ts, 24, 68)) +>K1 : Symbol(K1, Decl(genericObjectRest.ts, 24, 12)) +>k2 : Symbol(k2, Decl(genericObjectRest.ts, 24, 76)) +>K2 : Symbol(K2, Decl(genericObjectRest.ts, 24, 34)) + + let { [k1]: a1, [k2]: a2, ...r1 } = obj; +>k1 : Symbol(k1, Decl(genericObjectRest.ts, 24, 68)) +>a1 : Symbol(a1, Decl(genericObjectRest.ts, 25, 9)) +>k2 : Symbol(k2, Decl(genericObjectRest.ts, 24, 76)) +>a2 : Symbol(a2, Decl(genericObjectRest.ts, 25, 19)) +>r1 : Symbol(r1, Decl(genericObjectRest.ts, 25, 29)) +>obj : Symbol(obj, Decl(genericObjectRest.ts, 24, 58)) +} + diff --git a/tests/baselines/reference/genericObjectRest.types b/tests/baselines/reference/genericObjectRest.types new file mode 100644 index 0000000000000..c2fcaad7cb87c --- /dev/null +++ b/tests/baselines/reference/genericObjectRest.types @@ -0,0 +1,110 @@ +=== tests/cases/conformance/types/rest/genericObjectRest.ts === +const a = 'a'; +>a : "a" +>'a' : "a" + +function f1(obj: T) { +>f1 : (obj: T) => void +>a : string +>b : number +>obj : T + + let { ...r0 } = obj; +>r0 : T +>obj : T + + let { a: a1, ...r1 } = obj; +>a : any +>a1 : string +>r1 : Pick> +>obj : T + + let { a: a2, b: b2, ...r2 } = obj; +>a : any +>a2 : string +>b : any +>b2 : number +>r2 : Pick> +>obj : T + + let { 'a': a3, ...r3 } = obj; +>a3 : string +>r3 : Pick> +>obj : T + + let { ['a']: a4, ...r4 } = obj; +>'a' : "a" +>a4 : string +>r4 : Pick> +>obj : T + + let { [a]: a5, ...r5 } = obj; +>a : "a" +>a5 : string +>r5 : Pick> +>obj : T +} + +const sa = Symbol(); +>sa : unique symbol +>Symbol() : unique symbol +>Symbol : SymbolConstructor + +const sb = Symbol(); +>sb : unique symbol +>Symbol() : unique symbol +>Symbol : SymbolConstructor + +function f2(obj: T) { +>f2 : (obj: T) => void +>[sa] : string +>sa : unique symbol +>[sb] : number +>sb : unique symbol +>obj : T + + let { [sa]: a1, [sb]: b1, ...r1 } = obj; +>sa : unique symbol +>a1 : string +>sb : unique symbol +>b1 : number +>r1 : Pick> +>obj : T +} + +function f3(obj: T, k1: K1, k2: K2) { +>f3 : (obj: T, k1: K1, k2: K2) => void +>obj : T +>k1 : K1 +>k2 : K2 + + let { [k1]: a1, [k2]: a2, ...r1 } = obj; +>k1 : K1 +>a1 : T[K1] +>k2 : K2 +>a2 : T[K2] +>r1 : Pick> +>obj : T +} + +type Item = { a: string, b: number, c: boolean }; +>Item : Item +>a : string +>b : number +>c : boolean + +function f4(obj: Item, k1: K1, k2: K2) { +>f4 : (obj: Item, k1: K1, k2: K2) => void +>obj : Item +>k1 : K1 +>k2 : K2 + + let { [k1]: a1, [k2]: a2, ...r1 } = obj; +>k1 : K1 +>a1 : Item[K1] +>k2 : K2 +>a2 : Item[K2] +>r1 : Pick | Exclude<"b", K1 | K2> | Exclude<"c", K1 | K2>> +>obj : Item +} +