@@ -2245,7 +2245,7 @@ namespace ts {
2245
2245
writeUnionOrIntersectionType(<UnionOrIntersectionType>type, nextFlags);
2246
2246
}
2247
2247
else if (type.flags & TypeFlags.Spread) {
2248
- writeSpreadType(<SpreadType> type);
2248
+ writeSpreadType(type as SpreadType );
2249
2249
}
2250
2250
else if (getObjectFlags(type) & ObjectFlags.Anonymous) {
2251
2251
writeAnonymousType(<ObjectType>type, nextFlags);
@@ -3028,26 +3028,31 @@ namespace ts {
3028
3028
return symbol && getSymbolLinks(symbol).type || getTypeForVariableLikeDeclaration(node, /*includeOptionality*/ false);
3029
3029
}
3030
3030
3031
- function getTextOfPropertyName(name: PropertyName): string {
3032
- switch (name.kind) {
3033
- case SyntaxKind.Identifier:
3034
- return (<Identifier>name).text;
3035
- case SyntaxKind.StringLiteral:
3036
- case SyntaxKind.NumericLiteral:
3037
- return (<LiteralExpression>name).text;
3038
- case SyntaxKind.ComputedPropertyName:
3039
- if (isStringOrNumericLiteral((<ComputedPropertyName>name).expression.kind)) {
3040
- return (<LiteralExpression>(<ComputedPropertyName>name).expression).text;
3041
- }
3042
- }
3043
-
3044
- return undefined;
3045
- }
3046
-
3047
3031
function isComputedNonLiteralName(name: PropertyName): boolean {
3048
3032
return name.kind === SyntaxKind.ComputedPropertyName && !isStringOrNumericLiteral((<ComputedPropertyName>name).expression.kind);
3049
3033
}
3050
3034
3035
+ function getRestType(source: Type, properties: PropertyName[], symbol: Symbol): Type {
3036
+ Debug.assert(!!(source.flags & TypeFlags.Object), "Rest types only support object types right now.");
3037
+ const members = createMap<Symbol>();
3038
+ const names = createMap<true>();
3039
+ for (const name of properties) {
3040
+ names[getTextOfPropertyName(name)] = true;
3041
+ }
3042
+ for (const prop of getPropertiesOfType(source)) {
3043
+ const inNamesToRemove = prop.name in names;
3044
+ const isPrivate = getDeclarationModifierFlagsFromSymbol(prop) & (ModifierFlags.Private | ModifierFlags.Protected);
3045
+ const isMethod = prop.flags & SymbolFlags.Method;
3046
+ const isSetOnlyAccessor = prop.flags & SymbolFlags.SetAccessor && !(prop.flags & SymbolFlags.GetAccessor);
3047
+ if (!inNamesToRemove && !isPrivate && !isMethod && !isSetOnlyAccessor) {
3048
+ members[prop.name] = prop;
3049
+ }
3050
+ }
3051
+ const stringIndexInfo = getIndexInfoOfType(source, IndexKind.String);
3052
+ const numberIndexInfo = getIndexInfoOfType(source, IndexKind.Number);
3053
+ return createAnonymousType(symbol, members, emptyArray, emptyArray, stringIndexInfo, numberIndexInfo);
3054
+ }
3055
+
3051
3056
/** Return the inferred type for a binding element */
3052
3057
function getTypeForBindingElement(declaration: BindingElement): Type {
3053
3058
const pattern = <BindingPattern>declaration.parent;
@@ -3068,26 +3073,41 @@ namespace ts {
3068
3073
3069
3074
let type: Type;
3070
3075
if (pattern.kind === SyntaxKind.ObjectBindingPattern) {
3071
- // Use explicitly specified property name ({ p: xxx } form), or otherwise the implied name ({ p } form)
3072
- const name = declaration.propertyName || <Identifier>declaration.name;
3073
- if (isComputedNonLiteralName(name)) {
3074
- // computed properties with non-literal names are treated as 'any'
3075
- return anyType;
3076
- }
3077
- if (declaration.initializer) {
3078
- getContextualType(declaration.initializer);
3076
+ if (declaration.dotDotDotToken) {
3077
+ if (!(parentType.flags & TypeFlags.Object)) {
3078
+ error(declaration, Diagnostics.Rest_types_may_only_be_created_from_object_types);
3079
+ return unknownType;
3080
+ }
3081
+ const literalMembers: PropertyName[] = [];
3082
+ for (const element of pattern.elements) {
3083
+ if (element.kind !== SyntaxKind.OmittedExpression && !(element as BindingElement).dotDotDotToken) {
3084
+ literalMembers.push(element.propertyName || element.name as Identifier);
3085
+ }
3086
+ }
3087
+ type = getRestType(parentType, literalMembers, declaration.symbol);
3079
3088
}
3089
+ else {
3090
+ // Use explicitly specified property name ({ p: xxx } form), or otherwise the implied name ({ p } form)
3091
+ const name = declaration.propertyName || <Identifier>declaration.name;
3092
+ if (isComputedNonLiteralName(name)) {
3093
+ // computed properties with non-literal names are treated as 'any'
3094
+ return anyType;
3095
+ }
3096
+ if (declaration.initializer) {
3097
+ getContextualType(declaration.initializer);
3098
+ }
3080
3099
3081
- // Use type of the specified property, or otherwise, for a numeric name, the type of the numeric index signature,
3082
- // or otherwise the type of the string index signature.
3083
- const text = getTextOfPropertyName(name);
3100
+ // Use type of the specified property, or otherwise, for a numeric name, the type of the numeric index signature,
3101
+ // or otherwise the type of the string index signature.
3102
+ const text = getTextOfPropertyName(name);
3084
3103
3085
- type = getTypeOfPropertyOfType(parentType, text) ||
3086
- isNumericLiteralName(text) && getIndexTypeOfType(parentType, IndexKind.Number) ||
3087
- getIndexTypeOfType(parentType, IndexKind.String);
3088
- if (!type) {
3089
- error(name, Diagnostics.Type_0_has_no_property_1_and_no_string_index_signature, typeToString(parentType), declarationNameToString(name));
3090
- return unknownType;
3104
+ type = getTypeOfPropertyOfType(parentType, text) ||
3105
+ isNumericLiteralName(text) && getIndexTypeOfType(parentType, IndexKind.Number) ||
3106
+ getIndexTypeOfType(parentType, IndexKind.String);
3107
+ if (!type) {
3108
+ error(name, Diagnostics.Type_0_has_no_property_1_and_no_string_index_signature, typeToString(parentType), declarationNameToString(name));
3109
+ return unknownType;
3110
+ }
3091
3111
}
3092
3112
}
3093
3113
else {
@@ -3295,8 +3315,8 @@ namespace ts {
3295
3315
let hasComputedProperties = false;
3296
3316
forEach(pattern.elements, e => {
3297
3317
const name = e.propertyName || <Identifier>e.name;
3298
- if (isComputedNonLiteralName(name)) {
3299
- // do not include computed properties in the implied type
3318
+ if (isComputedNonLiteralName(name) || e.dotDotDotToken ) {
3319
+ // do not include computed properties or rests in the implied type
3300
3320
hasComputedProperties = true;
3301
3321
return;
3302
3322
}
@@ -14097,7 +14117,7 @@ namespace ts {
14097
14117
error(name, Diagnostics.Type_0_has_no_property_1_and_no_string_index_signature, typeToString(objectLiteralType), declarationNameToString(name));
14098
14118
}
14099
14119
}
14100
- else {
14120
+ else if (property.kind !== SyntaxKind.SpreadElementExpression) {
14101
14121
error(property, Diagnostics.Property_assignment_expected);
14102
14122
}
14103
14123
}
@@ -14143,7 +14163,7 @@ namespace ts {
14143
14163
}
14144
14164
else {
14145
14165
if (elementIndex < elements.length - 1) {
14146
- error(element, Diagnostics.A_rest_element_must_be_last_in_an_array_destructuring_pattern );
14166
+ error(element, Diagnostics.A_rest_element_must_be_last_in_a_destructuring_pattern );
14147
14167
}
14148
14168
else {
14149
14169
const restExpression = (<SpreadExpression>element).expression;
@@ -21058,7 +21078,7 @@ namespace ts {
21058
21078
if (node.dotDotDotToken) {
21059
21079
const elements = (<BindingPattern>node.parent).elements;
21060
21080
if (node !== lastOrUndefined(elements)) {
21061
- return grammarErrorOnNode(node, Diagnostics.A_rest_element_must_be_last_in_an_array_destructuring_pattern );
21081
+ return grammarErrorOnNode(node, Diagnostics.A_rest_element_must_be_last_in_a_destructuring_pattern );
21062
21082
}
21063
21083
21064
21084
if (node.name.kind === SyntaxKind.ArrayBindingPattern || node.name.kind === SyntaxKind.ObjectBindingPattern) {
0 commit comments