Skip to content

Commit ee23f93

Browse files
committed
Switch to 'unique symbol'
1 parent 43c151a commit ee23f93

70 files changed

Lines changed: 1291 additions & 1304 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/compiler/checker.ts

Lines changed: 80 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -2497,7 +2497,7 @@ namespace ts {
24972497
return (<IntrinsicType>type).intrinsicName === "true" ? createTrue() : createFalse();
24982498
}
24992499
if (type.flags & TypeFlags.UniqueESSymbol) {
2500-
return createESSymbolTypeNode();
2500+
return createTypeOperatorNode(SyntaxKind.UniqueKeyword, createKeywordTypeNode(SyntaxKind.SymbolKeyword));
25012501
}
25022502
if (type.flags & TypeFlags.Void) {
25032503
return createKeywordTypeNode(SyntaxKind.VoidKeyword);
@@ -3313,9 +3313,9 @@ namespace ts {
33133313
writeAnonymousType(<ObjectType>type, nextFlags);
33143314
}
33153315
else if (type.flags & TypeFlags.UniqueESSymbol) {
3316+
writeKeyword(writer, SyntaxKind.UniqueKeyword);
3317+
writeSpace(writer);
33163318
writeKeyword(writer, SyntaxKind.SymbolKeyword);
3317-
writePunctuation(writer, SyntaxKind.OpenParenToken);
3318-
writePunctuation(writer, SyntaxKind.CloseParenToken);
33193319
}
33203320
else if (type.flags & TypeFlags.StringOrNumberLiteral) {
33213321
writer.writeStringLiteral(literalTypeToString(<LiteralType>type));
@@ -4533,7 +4533,7 @@ namespace ts {
45334533
reportErrorsFromWidening(declaration, type);
45344534
}
45354535

4536-
// always widen a unique 'symbol()' type if the type was created for a different declaration.
4536+
// always widen a 'unique symbol' type if the type was created for a different declaration.
45374537
if (type.flags & TypeFlags.UniqueESSymbol && !declaration.type && type.symbol !== getSymbolOfNode(declaration)) {
45384538
type = esSymbolType;
45394539
}
@@ -5949,7 +5949,9 @@ namespace ts {
59495949
const modifiersType = getApparentType(getModifiersTypeFromMappedType(type)); // The 'T' in 'keyof T'
59505950
const templateReadonly = !!type.declaration.readonlyToken;
59515951
const templateOptional = !!type.declaration.questionToken;
5952-
if (type.declaration.typeParameter.constraint.kind === SyntaxKind.TypeOperator) {
5952+
const constraintDeclaration = type.declaration.typeParameter.constraint;
5953+
if (constraintDeclaration.kind === SyntaxKind.TypeOperator &&
5954+
(<TypeOperatorNode>constraintDeclaration).operator === SyntaxKind.KeyOfKeyword) {
59535955
// We have a { [P in keyof T]: X }
59545956
for (const propertySymbol of getPropertiesOfType(modifiersType)) {
59555957
addMemberForKeyType(getLiteralTypeFromPropertyName(propertySymbol), propertySymbol);
@@ -6024,7 +6026,8 @@ namespace ts {
60246026
function getModifiersTypeFromMappedType(type: MappedType) {
60256027
if (!type.modifiersType) {
60266028
const constraintDeclaration = type.declaration.typeParameter.constraint;
6027-
if (constraintDeclaration.kind === SyntaxKind.TypeOperator) {
6029+
if (constraintDeclaration.kind === SyntaxKind.TypeOperator &&
6030+
(<TypeOperatorNode>constraintDeclaration).operator === SyntaxKind.KeyOfKeyword) {
60286031
// If the constraint declaration is a 'keyof T' node, the modifiers type is T. We check
60296032
// AST nodes here because, when T is a non-generic type, the logic below eagerly resolves
60306033
// 'keyof T' to a literal union type and we can't recover T from that type.
@@ -7822,7 +7825,21 @@ namespace ts {
78227825
function getTypeFromTypeOperatorNode(node: TypeOperatorNode) {
78237826
const links = getNodeLinks(node);
78247827
if (!links.resolvedType) {
7825-
links.resolvedType = getIndexType(getTypeFromTypeNode(node.type));
7828+
switch (node.operator) {
7829+
case SyntaxKind.KeyOfKeyword:
7830+
links.resolvedType = getIndexType(getTypeFromTypeNode(node.type));
7831+
break;
7832+
case SyntaxKind.UniqueKeyword:
7833+
if (node.type.kind === SyntaxKind.SymbolKeyword) {
7834+
const parent = skipParentheses(node).parent;
7835+
const symbol = getSymbolOfNode(parent);
7836+
links.resolvedType = symbol ? getUniqueESSymbolTypeForSymbol(symbol) : esSymbolType;
7837+
}
7838+
else {
7839+
links.resolvedType = unknownType;
7840+
}
7841+
break;
7842+
}
78267843
}
78277844
return links.resolvedType;
78287845
}
@@ -8226,21 +8243,6 @@ namespace ts {
82268243
return esSymbolType;
82278244
}
82288245

8229-
function getTypeFromESSymbolTypeNode(node: ESSymbolTypeNode): Type {
8230-
const links = getNodeLinks(node);
8231-
if (!links.resolvedType) {
8232-
const parent = skipParentheses(node).parent;
8233-
const symbol = getSymbolOfNode(parent);
8234-
if (symbol) {
8235-
links.resolvedType = getUniqueESSymbolTypeForSymbol(symbol);
8236-
}
8237-
else {
8238-
links.resolvedType = esSymbolType;
8239-
}
8240-
}
8241-
return links.resolvedType;
8242-
}
8243-
82448246
function getTypeFromJSDocVariadicType(node: JSDocVariadicType): Type {
82458247
const links = getNodeLinks(node);
82468248
if (!links.resolvedType) {
@@ -8300,8 +8302,6 @@ namespace ts {
83008302
return getTypeFromThisTypeNode(node as ThisExpression | ThisTypeNode);
83018303
case SyntaxKind.LiteralType:
83028304
return getTypeFromLiteralTypeNode(<LiteralTypeNode>node);
8303-
case SyntaxKind.ESSymbolType:
8304-
return getTypeFromESSymbolTypeNode(<ESSymbolTypeNode>node);
83058305
case SyntaxKind.TypeReference:
83068306
return getTypeFromTypeReference(<TypeReferenceNode>node);
83078307
case SyntaxKind.TypePredicate:
@@ -17313,7 +17313,7 @@ namespace ts {
1731317313
type = checkAwaitedType(type, /*errorNode*/ func, Diagnostics.The_return_type_of_an_async_function_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member);
1731417314
}
1731517315

17316-
// widen 'symbol()' types when we infer the return type.
17316+
// widen 'unique symbol' types when we infer the return type.
1731717317
type = getWidenedTypeOfUniqueESSymbolType(type);
1731817318
}
1731917319
else {
@@ -17349,7 +17349,7 @@ namespace ts {
1734917349
// Return a union of the return expression types.
1735017350
type = getUnionType(types, /*subtypeReduction*/ true);
1735117351

17352-
// widen 'symbol()' types when we infer the return type.
17352+
// widen 'unique symbol' types when we infer the return type.
1735317353
type = getWidenedTypeOfUniqueESSymbolType(type);
1735417354

1735517355
if (functionFlags & FunctionFlags.Generator) { // AsyncGenerator function or Generator function
@@ -19428,8 +19428,9 @@ namespace ts {
1942819428
checkTypeAssignableTo(constraintType, stringType, node.typeParameter.constraint);
1942919429
}
1943019430

19431-
function checkSymbolType(node: ESSymbolTypeNode) {
19432-
checkGrammarESSymbolTypeNode(node);
19431+
function checkTypeOperator(node: TypeOperatorNode) {
19432+
checkGrammarTypeOperatorNode(node);
19433+
checkSourceElement(node.type);
1943319434
}
1943419435

1943519436
function isPrivateWithinAmbient(node: Node): boolean {
@@ -23000,8 +23001,9 @@ namespace ts {
2300023001
case SyntaxKind.IntersectionType:
2300123002
return checkUnionOrIntersectionType(<UnionOrIntersectionTypeNode>node);
2300223003
case SyntaxKind.ParenthesizedType:
23003-
case SyntaxKind.TypeOperator:
2300423004
return checkSourceElement((<ParenthesizedTypeNode | TypeOperatorNode>node).type);
23005+
case SyntaxKind.TypeOperator:
23006+
return checkTypeOperator(<TypeOperatorNode>node);
2300523007
case SyntaxKind.JSDocAugmentsTag:
2300623008
return checkJSDocAugmentsTag(node as JSDocAugmentsTag);
2300723009
case SyntaxKind.JSDocTypedefTag:
@@ -23026,8 +23028,6 @@ namespace ts {
2302623028
return checkIndexedAccessType(<IndexedAccessTypeNode>node);
2302723029
case SyntaxKind.MappedType:
2302823030
return checkMappedType(<MappedTypeNode>node);
23029-
case SyntaxKind.ESSymbolType:
23030-
return checkSymbolType(<ESSymbolTypeNode>node);
2303123031
case SyntaxKind.FunctionDeclaration:
2303223032
return checkFunctionDeclaration(<FunctionDeclaration>node);
2303323033
case SyntaxKind.Block:
@@ -25341,54 +25341,60 @@ namespace ts {
2534125341
}
2534225342
}
2534325343

25344-
function checkGrammarESSymbolTypeNode(node: ESSymbolTypeNode) {
25345-
let parent = node.parent;
25346-
while (parent.kind === SyntaxKind.ParenthesizedType) {
25347-
parent = parent.parent;
25348-
}
25344+
function checkGrammarTypeOperatorNode(node: TypeOperatorNode) {
25345+
if (node.operator === SyntaxKind.UniqueKeyword) {
25346+
if (node.type.kind !== SyntaxKind.SymbolKeyword) {
25347+
return grammarErrorOnNode(node.type, Diagnostics._0_expected, tokenToString(SyntaxKind.SymbolKeyword));
25348+
}
2534925349

25350-
switch (parent.kind) {
25351-
case SyntaxKind.VariableDeclaration:
25352-
const decl = parent as VariableDeclaration;
25353-
if (decl.name.kind !== SyntaxKind.Identifier) {
25354-
return grammarErrorOnNode(node, Diagnostics.Unique_symbol_types_may_not_be_used_on_a_variable_declaration_with_a_binding_name);
25355-
}
25356-
if (!isVariableDeclarationInVariableStatement(decl)) {
25357-
return grammarErrorOnNode(node, Diagnostics.Unique_symbol_types_are_only_allowed_on_variables_in_a_variable_statement);
25358-
}
25359-
if (!(decl.parent.flags & NodeFlags.Const)) {
25360-
return grammarErrorOnNode((<VariableDeclaration>parent).name, Diagnostics.A_variable_whose_type_is_a_unique_symbol_type_must_be_const);
25361-
}
25362-
break;
25350+
let parent = node.parent;
25351+
while (parent.kind === SyntaxKind.ParenthesizedType) {
25352+
parent = parent.parent;
25353+
}
2536325354

25364-
case SyntaxKind.PropertyDeclaration:
25365-
if (!hasModifier(parent, ModifierFlags.Static) ||
25366-
!hasModifier(parent, ModifierFlags.Readonly)) {
25367-
return grammarErrorOnNode((<PropertyDeclaration>parent).name, Diagnostics.A_property_of_a_class_whose_type_is_a_unique_symbol_type_must_be_both_static_and_readonly);
25368-
}
25369-
break;
25355+
switch (parent.kind) {
25356+
case SyntaxKind.VariableDeclaration:
25357+
const decl = parent as VariableDeclaration;
25358+
if (decl.name.kind !== SyntaxKind.Identifier) {
25359+
return grammarErrorOnNode(node, Diagnostics.unique_symbol_types_may_not_be_used_on_a_variable_declaration_with_a_binding_name);
25360+
}
25361+
if (!isVariableDeclarationInVariableStatement(decl)) {
25362+
return grammarErrorOnNode(node, Diagnostics.unique_symbol_types_are_only_allowed_on_variables_in_a_variable_statement);
25363+
}
25364+
if (!(decl.parent.flags & NodeFlags.Const)) {
25365+
return grammarErrorOnNode((<VariableDeclaration>parent).name, Diagnostics.A_variable_whose_type_is_a_unique_symbol_type_must_be_const);
25366+
}
25367+
break;
2537025368

25371-
case SyntaxKind.PropertySignature:
25372-
if (!hasModifier(parent, ModifierFlags.Readonly)) {
25373-
return grammarErrorOnNode((<PropertySignature>parent).name, Diagnostics.A_property_of_an_interface_or_type_literal_whose_type_is_a_unique_symbol_type_must_be_readonly);
25374-
}
25375-
break;
25369+
case SyntaxKind.PropertyDeclaration:
25370+
if (!hasModifier(parent, ModifierFlags.Static) ||
25371+
!hasModifier(parent, ModifierFlags.Readonly)) {
25372+
return grammarErrorOnNode((<PropertyDeclaration>parent).name, Diagnostics.A_property_of_a_class_whose_type_is_a_unique_symbol_type_must_be_both_static_and_readonly);
25373+
}
25374+
break;
2537625375

25377-
// report specific errors for cases where a `symbol()` type is disallowed even when it is in a `const` or `readonly` declaration.
25378-
case SyntaxKind.UnionType:
25379-
return grammarErrorOnNode(node, Diagnostics.Unique_symbol_types_are_not_allowed_in_a_union_type);
25380-
case SyntaxKind.IntersectionType:
25381-
return grammarErrorOnNode(node, Diagnostics.Unique_symbol_types_are_not_allowed_in_an_intersection_type);
25382-
case SyntaxKind.ArrayType:
25383-
return grammarErrorOnNode(node, Diagnostics.Unique_symbol_types_are_not_allowed_in_an_array_type);
25384-
case SyntaxKind.TupleType:
25385-
return grammarErrorOnNode(node, Diagnostics.Unique_symbol_types_are_not_allowed_in_a_tuple_type);
25386-
case SyntaxKind.MappedType:
25387-
return grammarErrorOnNode(node, Diagnostics.Unique_symbol_types_are_not_allowed_in_a_mapped_type);
25376+
case SyntaxKind.PropertySignature:
25377+
if (!hasModifier(parent, ModifierFlags.Readonly)) {
25378+
return grammarErrorOnNode((<PropertySignature>parent).name, Diagnostics.A_property_of_an_interface_or_type_literal_whose_type_is_a_unique_symbol_type_must_be_readonly);
25379+
}
25380+
break;
2538825381

25389-
// report a general error for any other invalid use site.
25390-
default:
25391-
return grammarErrorOnNode(node, Diagnostics.Unique_symbol_types_are_not_allowed_here);
25382+
// report specific errors for cases where a `unique symbol` type is disallowed even when it is in a `const` or `readonly` declaration.
25383+
case SyntaxKind.UnionType:
25384+
return grammarErrorOnNode(node, Diagnostics.unique_symbol_types_are_not_allowed_in_a_union_type);
25385+
case SyntaxKind.IntersectionType:
25386+
return grammarErrorOnNode(node, Diagnostics.unique_symbol_types_are_not_allowed_in_an_intersection_type);
25387+
case SyntaxKind.ArrayType:
25388+
return grammarErrorOnNode(node, Diagnostics.unique_symbol_types_are_not_allowed_in_an_array_type);
25389+
case SyntaxKind.TupleType:
25390+
return grammarErrorOnNode(node, Diagnostics.unique_symbol_types_are_not_allowed_in_a_tuple_type);
25391+
case SyntaxKind.MappedType:
25392+
return grammarErrorOnNode(node, Diagnostics.unique_symbol_types_are_not_allowed_in_a_mapped_type);
25393+
25394+
// report a general error for any other invalid use site.
25395+
default:
25396+
return grammarErrorOnNode(node, Diagnostics.unique_symbol_types_are_not_allowed_here);
25397+
}
2539225398
}
2539325399
}
2539425400

src/compiler/declarationEmitter.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -425,8 +425,6 @@ namespace ts {
425425
case SyntaxKind.ThisType:
426426
case SyntaxKind.LiteralType:
427427
return writeTextOfNode(currentText, type);
428-
case SyntaxKind.ESSymbolType:
429-
return write("symbol()");
430428
case SyntaxKind.ExpressionWithTypeArguments:
431429
return emitExpressionWithTypeArguments(<ExpressionWithTypeArguments>type);
432430
case SyntaxKind.TypeReference:

0 commit comments

Comments
 (0)