Skip to content

Commit 6f8959b

Browse files
committed
Use Rest<T, K> for rest properties in object destructuring
1 parent f555261 commit 6f8959b

File tree

1 file changed

+30
-29
lines changed

1 file changed

+30
-29
lines changed

src/compiler/checker.ts

Lines changed: 30 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -517,6 +517,7 @@ namespace ts {
517517
let deferredGlobalTemplateStringsArrayType: ObjectType;
518518
let deferredGlobalImportMetaType: ObjectType;
519519
let deferredGlobalExtractSymbol: Symbol;
520+
let deferredGlobalRestSymbol: Symbol;
520521

521522
const allPotentiallyUnusedIdentifiers = createMap<PotentiallyUnusedIdentifier[]>(); // key is file name
522523

@@ -4596,26 +4597,18 @@ namespace ts {
45964597
if (source.flags & TypeFlags.Never) {
45974598
return emptyObjectType;
45984599
}
4599-
46004600
if (source.flags & TypeFlags.Union) {
46014601
return mapType(source, t => getRestType(t, properties, symbol));
46024602
}
4603-
4604-
const members = createSymbolTable();
4605-
const names = createUnderscoreEscapedMap<true>();
4606-
for (const name of properties) {
4607-
names.set(getTextOfPropertyName(name), true);
4603+
const restTypeAlias = getGlobalRestSymbol();
4604+
if (!restTypeAlias) {
4605+
return errorType;
46084606
}
4609-
for (const prop of getPropertiesOfType(source)) {
4610-
if (!names.has(prop.escapedName)
4611-
&& !(getDeclarationModifierFlagsFromSymbol(prop) & (ModifierFlags.Private | ModifierFlags.Protected))
4612-
&& isSpreadableProperty(prop)) {
4613-
members.set(prop.escapedName, getSpreadSymbol(prop));
4614-
}
4607+
const omitTypes = getUnionType(map(properties, getLiteralTypeFromPropertyName));
4608+
if (omitTypes.flags & TypeFlags.Never) {
4609+
return source;
46154610
}
4616-
const stringIndexInfo = getIndexInfoOfType(source, IndexKind.String);
4617-
const numberIndexInfo = getIndexInfoOfType(source, IndexKind.Number);
4618-
return createAnonymousType(symbol, members, emptyArray, emptyArray, stringIndexInfo, numberIndexInfo);
4611+
return getTypeAliasInstantiation(restTypeAlias, [source, omitTypes]);
46194612
}
46204613

46214614
/** Return the inferred type for a binding element */
@@ -4639,7 +4632,7 @@ namespace ts {
46394632
let type: Type | undefined;
46404633
if (pattern.kind === SyntaxKind.ObjectBindingPattern) {
46414634
if (declaration.dotDotDotToken) {
4642-
if (parentType.flags & TypeFlags.Unknown || !isValidSpreadType(parentType) || isGenericObjectType(parentType)) {
4635+
if (parentType.flags & TypeFlags.Unknown || !isValidSpreadType(parentType)) {
46434636
error(declaration, Diagnostics.Rest_types_may_only_be_created_from_object_types);
46444637
return errorType;
46454638
}
@@ -6823,7 +6816,7 @@ namespace ts {
68236816
if (isMappedTypeWithKeyofConstraintDeclaration(type)) {
68246817
// We have a { [P in keyof T]: X }
68256818
for (const prop of getPropertiesOfType(modifiersType)) {
6826-
addMemberForKeyType(getLiteralTypeFromPropertyName(prop, include));
6819+
addMemberForKeyType(getLiteralTypeFromProperty(prop, include));
68276820
}
68286821
if (modifiersType.flags & TypeFlags.Any || getIndexInfoOfType(modifiersType, IndexKind.String)) {
68296822
addMemberForKeyType(stringType);
@@ -8674,6 +8667,10 @@ namespace ts {
86748667
return deferredGlobalExtractSymbol || (deferredGlobalExtractSymbol = getGlobalSymbol("Extract" as __String, SymbolFlags.TypeAlias, Diagnostics.Cannot_find_global_type_0)!); // TODO: GH#18217
86758668
}
86768669

8670+
function getGlobalRestSymbol(): Symbol {
8671+
return deferredGlobalRestSymbol || (deferredGlobalRestSymbol = getGlobalSymbol("Rest" as __String, SymbolFlags.TypeAlias, Diagnostics.Cannot_find_global_type_0)!); // TODO: GH#18217
8672+
}
8673+
86778674
/**
86788675
* Instantiates a global type that is generic with some element type, and returns that instantiation.
86798676
*/
@@ -9256,14 +9253,18 @@ namespace ts {
92569253
type.resolvedIndexType || (type.resolvedIndexType = createIndexType(type, /*stringsOnly*/ false));
92579254
}
92589255

9259-
function getLiteralTypeFromPropertyName(prop: Symbol, include: TypeFlags) {
9256+
function getLiteralTypeFromPropertyName(name: PropertyName) {
9257+
return isComputedPropertyName(name) ? checkComputedPropertyName(name) :
9258+
isIdentifier(name) ? getLiteralType(unescapeLeadingUnderscores(name.escapedText)) :
9259+
checkExpression(name);
9260+
}
9261+
9262+
function getLiteralTypeFromProperty(prop: Symbol, include: TypeFlags) {
92609263
if (!(getDeclarationModifierFlagsFromSymbol(prop) & ModifierFlags.NonPublicAccessibilityModifier)) {
92619264
let type = getLateBoundSymbol(prop).nameType;
92629265
if (!type && !isKnownSymbol(prop)) {
9263-
const name = prop.valueDeclaration && getNameOfDeclaration(prop.valueDeclaration);
9264-
type = name && isNumericLiteral(name) ? getLiteralType(+name.text) :
9265-
name && name.kind === SyntaxKind.ComputedPropertyName && isNumericLiteral(name.expression) ? getLiteralType(+name.expression.text) :
9266-
getLiteralType(symbolName(prop));
9266+
const name = prop.valueDeclaration && getNameOfDeclaration(prop.valueDeclaration) as PropertyName;
9267+
type = name && getLiteralTypeFromPropertyName(name) || getLiteralType(symbolName(prop));
92679268
}
92689269
if (type && type.flags & include) {
92699270
return type;
@@ -9272,8 +9273,8 @@ namespace ts {
92729273
return neverType;
92739274
}
92749275

9275-
function getLiteralTypeFromPropertyNames(type: Type, include: TypeFlags) {
9276-
return getUnionType(map(getPropertiesOfType(type), t => getLiteralTypeFromPropertyName(t, include)));
9276+
function getLiteralTypeFromProperties(type: Type, include: TypeFlags) {
9277+
return getUnionType(map(getPropertiesOfType(type), t => getLiteralTypeFromProperty(t, include)));
92779278
}
92789279

92799280
function getNonEnumNumberIndexInfo(type: Type) {
@@ -9288,10 +9289,10 @@ namespace ts {
92889289
getObjectFlags(type) & ObjectFlags.Mapped ? getConstraintTypeFromMappedType(<MappedType>type) :
92899290
type === wildcardType ? wildcardType :
92909291
type.flags & TypeFlags.Any ? keyofConstraintType :
9291-
stringsOnly ? getIndexInfoOfType(type, IndexKind.String) ? stringType : getLiteralTypeFromPropertyNames(type, TypeFlags.StringLiteral) :
9292-
getIndexInfoOfType(type, IndexKind.String) ? getUnionType([stringType, numberType, getLiteralTypeFromPropertyNames(type, TypeFlags.UniqueESSymbol)]) :
9293-
getNonEnumNumberIndexInfo(type) ? getUnionType([numberType, getLiteralTypeFromPropertyNames(type, TypeFlags.StringLiteral | TypeFlags.UniqueESSymbol)]) :
9294-
getLiteralTypeFromPropertyNames(type, TypeFlags.StringOrNumberLiteralOrUnique);
9292+
stringsOnly ? getIndexInfoOfType(type, IndexKind.String) ? stringType : getLiteralTypeFromProperties(type, TypeFlags.StringLiteral) :
9293+
getIndexInfoOfType(type, IndexKind.String) ? getUnionType([stringType, numberType, getLiteralTypeFromProperties(type, TypeFlags.UniqueESSymbol)]) :
9294+
getNonEnumNumberIndexInfo(type) ? getUnionType([numberType, getLiteralTypeFromProperties(type, TypeFlags.StringLiteral | TypeFlags.UniqueESSymbol)]) :
9295+
getLiteralTypeFromProperties(type, TypeFlags.StringOrNumberLiteralOrUnique);
92959296
}
92969297

92979298
function getExtractStringType(type: Type) {
@@ -10976,7 +10977,7 @@ namespace ts {
1097610977
if (!length(node.properties)) return;
1097710978
for (const prop of node.properties) {
1097810979
if (isSpreadAssignment(prop)) continue;
10979-
const type = getLiteralTypeFromPropertyName(getSymbolOfNode(prop), TypeFlags.StringOrNumberLiteralOrUnique);
10980+
const type = getLiteralTypeFromProperty(getSymbolOfNode(prop), TypeFlags.StringOrNumberLiteralOrUnique);
1098010981
if (!type || (type.flags & TypeFlags.Never)) {
1098110982
continue;
1098210983
}

0 commit comments

Comments
 (0)