Skip to content

Commit 99f352f

Browse files
committed
Rest of untyped binding pattern is string-indexed type
This is more correct than any and the code is more elegant as well.
1 parent f85ca9c commit 99f352f

File tree

1 file changed

+10
-13
lines changed

1 file changed

+10
-13
lines changed

src/compiler/checker.ts

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3099,15 +3099,6 @@ namespace ts {
30993099
error(declaration, Diagnostics.Rest_types_may_only_be_created_from_object_types);
31003100
return unknownType;
31013101
}
3102-
const parent = pattern.parent as VariableLikeDeclaration;
3103-
if (parent.kind === SyntaxKind.Parameter &&
3104-
!parent.type &&
3105-
!parent.initializer &&
3106-
!getContextuallyTypedParameterType(parent as ParameterDeclaration)) {
3107-
// if this type came from examining the structure of the pattern --
3108-
// there was no other information -- then it is not sufficient to determine the rest type, so just return any
3109-
return anyType;
3110-
}
31113102
const literalMembers: PropertyName[] = [];
31123103
for (const element of pattern.elements) {
31133104
if (!(element as BindingElement).dotDotDotToken) {
@@ -3318,14 +3309,19 @@ namespace ts {
33183309
// Return the type implied by an object binding pattern
33193310
function getTypeFromObjectBindingPattern(pattern: ObjectBindingPattern, includePatternInType: boolean, reportErrors: boolean): Type {
33203311
const members = createMap<Symbol>();
3312+
let stringIndexInfo: IndexInfo;
33213313
let hasComputedProperties = false;
33223314
forEach(pattern.elements, e => {
33233315
const name = e.propertyName || <Identifier>e.name;
3324-
if (isComputedNonLiteralName(name) || e.dotDotDotToken) {
3325-
// do not include computed properties or rests in the implied type
3316+
if (isComputedNonLiteralName(name)) {
3317+
// do not include computed properties in the implied type
33263318
hasComputedProperties = true;
33273319
return;
33283320
}
3321+
if (e.dotDotDotToken) {
3322+
stringIndexInfo = createIndexInfo(anyType, /*isReadonly*/ false);
3323+
return;
3324+
}
33293325

33303326
const text = getTextOfPropertyName(name);
33313327
const flags = SymbolFlags.Property | SymbolFlags.Transient | (e.initializer ? SymbolFlags.Optional : 0);
@@ -3334,7 +3330,7 @@ namespace ts {
33343330
symbol.bindingElement = e;
33353331
members[symbol.name] = symbol;
33363332
});
3337-
const result = createAnonymousType(undefined, members, emptyArray, emptyArray, undefined, undefined);
3333+
const result = createAnonymousType(undefined, members, emptyArray, emptyArray, stringIndexInfo, undefined);
33383334
if (includePatternInType) {
33393335
result.pattern = pattern;
33403336
}
@@ -11422,7 +11418,8 @@ namespace ts {
1142211418
if (impliedProp) {
1142311419
prop.flags |= impliedProp.flags & SymbolFlags.Optional;
1142411420
}
11425-
else if (!compilerOptions.suppressExcessPropertyErrors) {
11421+
11422+
else if (!compilerOptions.suppressExcessPropertyErrors && !getIndexInfoOfType(contextualType, IndexKind.String)) {
1142611423
error(memberDecl.name, Diagnostics.Object_literal_may_only_specify_known_properties_and_0_does_not_exist_in_type_1,
1142711424
symbolToString(member), typeToString(contextualType));
1142811425
}

0 commit comments

Comments
 (0)