From 9853f5f271092d02f578faf6c0856d9d85ec7405 Mon Sep 17 00:00:00 2001 From: Michael FIG Date: Mon, 10 Aug 2026 13:32:31 -0600 Subject: [PATCH 1/6] New RegisteredSymbol intrinsic --- .../registeredSymbolIntrinsic.symbols | 63 +++++++++++++++ .../compiler/registeredSymbolIntrinsic.types | 65 ++++++++++++++++ .../compiler/registeredSymbolIntrinsic.ts | 19 +++++ .../bundled/libs/lib.es2015.symbol.d.ts | 4 +- tsc/internal/checker/checker.go | 77 ++++++++++++++++--- tsc/internal/checker/nodebuilderimpl.go | 8 ++ 6 files changed, 223 insertions(+), 13 deletions(-) create mode 100644 testdata/baselines/reference/compiler/registeredSymbolIntrinsic.symbols create mode 100644 testdata/baselines/reference/compiler/registeredSymbolIntrinsic.types create mode 100644 testdata/tests/cases/compiler/registeredSymbolIntrinsic.ts diff --git a/testdata/baselines/reference/compiler/registeredSymbolIntrinsic.symbols b/testdata/baselines/reference/compiler/registeredSymbolIntrinsic.symbols new file mode 100644 index 0000000000000..41f68d3515f0b --- /dev/null +++ b/testdata/baselines/reference/compiler/registeredSymbolIntrinsic.symbols @@ -0,0 +1,63 @@ +//// [tests/cases/compiler/registeredSymbolIntrinsic.ts] //// + +=== registeredSymbolIntrinsic.ts === +const foo = Symbol.for("foo"); +>foo : Symbol(foo, Decl(registeredSymbolIntrinsic.ts, 0, 5)) +>Symbol.for : Symbol(SymbolConstructor.for, Decl(lib.es2015.symbol.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>for : Symbol(SymbolConstructor.for, Decl(lib.es2015.symbol.d.ts, --, --)) + +const fooAgain = Symbol.for("foo"); +>fooAgain : Symbol(fooAgain, Decl(registeredSymbolIntrinsic.ts, 1, 5)) +>Symbol.for : Symbol(SymbolConstructor.for, Decl(lib.es2015.symbol.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>for : Symbol(SymbolConstructor.for, Decl(lib.es2015.symbol.d.ts, --, --)) + +const bar = Symbol.for("bar"); +>bar : Symbol(bar, Decl(registeredSymbolIntrinsic.ts, 2, 5)) +>Symbol.for : Symbol(SymbolConstructor.for, Decl(lib.es2015.symbol.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>for : Symbol(SymbolConstructor.for, Decl(lib.es2015.symbol.d.ts, --, --)) + +let sameStringKey: typeof foo = fooAgain; +>sameStringKey : Symbol(sameStringKey, Decl(registeredSymbolIntrinsic.ts, 4, 3)) +>foo : Symbol(foo, Decl(registeredSymbolIntrinsic.ts, 0, 5)) +>fooAgain : Symbol(fooAgain, Decl(registeredSymbolIntrinsic.ts, 1, 5)) + +let registeredStringKey: RegisteredSymbol<"foo"> = foo; +>registeredStringKey : Symbol(registeredStringKey, Decl(registeredSymbolIntrinsic.ts, 5, 3)) +>RegisteredSymbol : Symbol(RegisteredSymbol, Decl(lib.es2015.symbol.d.ts, --, --)) +>foo : Symbol(foo, Decl(registeredSymbolIntrinsic.ts, 0, 5)) + +let registeredBarKey: RegisteredSymbol<"bar"> = bar; +>registeredBarKey : Symbol(registeredBarKey, Decl(registeredSymbolIntrinsic.ts, 6, 3)) +>RegisteredSymbol : Symbol(RegisteredSymbol, Decl(lib.es2015.symbol.d.ts, --, --)) +>bar : Symbol(bar, Decl(registeredSymbolIntrinsic.ts, 2, 5)) + +let widenedSymbol: symbol = foo; +>widenedSymbol : Symbol(widenedSymbol, Decl(registeredSymbolIntrinsic.ts, 7, 3)) +>foo : Symbol(foo, Decl(registeredSymbolIntrinsic.ts, 0, 5)) + +declare const key: string; +>key : Symbol(key, Decl(registeredSymbolIntrinsic.ts, 9, 13)) + +let registeredString: RegisteredSymbol = Symbol.for(key); +>registeredString : Symbol(registeredString, Decl(registeredSymbolIntrinsic.ts, 10, 3)) +>RegisteredSymbol : Symbol(RegisteredSymbol, Decl(lib.es2015.symbol.d.ts, --, --)) +>Symbol.for : Symbol(SymbolConstructor.for, Decl(lib.es2015.symbol.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>for : Symbol(SymbolConstructor.for, Decl(lib.es2015.symbol.d.ts, --, --)) +>key : Symbol(key, Decl(registeredSymbolIntrinsic.ts, 9, 13)) + +interface WithRegisteredKeys { +>WithRegisteredKeys : Symbol(WithRegisteredKeys, Decl(registeredSymbolIntrinsic.ts, 10, 65)) + + [foo]: string; +>[foo] : Symbol(WithRegisteredKeys[foo], Decl(registeredSymbolIntrinsic.ts, 12, 30)) +>foo : Symbol(foo, Decl(registeredSymbolIntrinsic.ts, 0, 5)) + + [bar]: number; +>[bar] : Symbol(WithRegisteredKeys[bar], Decl(registeredSymbolIntrinsic.ts, 13, 18)) +>bar : Symbol(bar, Decl(registeredSymbolIntrinsic.ts, 2, 5)) +} + diff --git a/testdata/baselines/reference/compiler/registeredSymbolIntrinsic.types b/testdata/baselines/reference/compiler/registeredSymbolIntrinsic.types new file mode 100644 index 0000000000000..d12d6444c725a --- /dev/null +++ b/testdata/baselines/reference/compiler/registeredSymbolIntrinsic.types @@ -0,0 +1,65 @@ +//// [tests/cases/compiler/registeredSymbolIntrinsic.ts] //// + +=== registeredSymbolIntrinsic.ts === +const foo = Symbol.for("foo"); +>foo : RegisteredSymbol<"foo"> +>Symbol.for("foo") : RegisteredSymbol<"foo"> +>Symbol.for : (key: Key) => RegisteredSymbol +>Symbol : SymbolConstructor +>for : (key: Key) => RegisteredSymbol +>"foo" : "foo" + +const fooAgain = Symbol.for("foo"); +>fooAgain : RegisteredSymbol<"foo"> +>Symbol.for("foo") : RegisteredSymbol<"foo"> +>Symbol.for : (key: Key) => RegisteredSymbol +>Symbol : SymbolConstructor +>for : (key: Key) => RegisteredSymbol +>"foo" : "foo" + +const bar = Symbol.for("bar"); +>bar : RegisteredSymbol<"bar"> +>Symbol.for("bar") : RegisteredSymbol<"bar"> +>Symbol.for : (key: Key) => RegisteredSymbol +>Symbol : SymbolConstructor +>for : (key: Key) => RegisteredSymbol +>"bar" : "bar" + +let sameStringKey: typeof foo = fooAgain; +>sameStringKey : RegisteredSymbol<"foo"> +>foo : RegisteredSymbol<"foo"> +>fooAgain : RegisteredSymbol<"foo"> + +let registeredStringKey: RegisteredSymbol<"foo"> = foo; +>registeredStringKey : RegisteredSymbol<"foo"> +>foo : RegisteredSymbol<"foo"> + +let registeredBarKey: RegisteredSymbol<"bar"> = bar; +>registeredBarKey : RegisteredSymbol<"bar"> +>bar : RegisteredSymbol<"bar"> + +let widenedSymbol: symbol = foo; +>widenedSymbol : symbol +>foo : RegisteredSymbol<"foo"> + +declare const key: string; +>key : string + +let registeredString: RegisteredSymbol = Symbol.for(key); +>registeredString : RegisteredSymbol +>Symbol.for(key) : RegisteredSymbol +>Symbol.for : (key: Key) => RegisteredSymbol +>Symbol : SymbolConstructor +>for : (key: Key) => RegisteredSymbol +>key : string + +interface WithRegisteredKeys { + [foo]: string; +>[foo] : string +>foo : RegisteredSymbol<"foo"> + + [bar]: number; +>[bar] : number +>bar : RegisteredSymbol<"bar"> +} + diff --git a/testdata/tests/cases/compiler/registeredSymbolIntrinsic.ts b/testdata/tests/cases/compiler/registeredSymbolIntrinsic.ts new file mode 100644 index 0000000000000..d245ad80a7e20 --- /dev/null +++ b/testdata/tests/cases/compiler/registeredSymbolIntrinsic.ts @@ -0,0 +1,19 @@ +// @target: es2015 +// @noEmit: true + +const foo = Symbol.for("foo"); +const fooAgain = Symbol.for("foo"); +const bar = Symbol.for("bar"); + +let sameStringKey: typeof foo = fooAgain; +let registeredStringKey: RegisteredSymbol<"foo"> = foo; +let registeredBarKey: RegisteredSymbol<"bar"> = bar; +let widenedSymbol: symbol = foo; + +declare const key: string; +let registeredString: RegisteredSymbol = Symbol.for(key); + +interface WithRegisteredKeys { + [foo]: string; + [bar]: number; +} diff --git a/tsc/internal/bundled/libs/lib.es2015.symbol.d.ts b/tsc/internal/bundled/libs/lib.es2015.symbol.d.ts index b2ba22dba66fa..36f295fe2874a 100644 --- a/tsc/internal/bundled/libs/lib.es2015.symbol.d.ts +++ b/tsc/internal/bundled/libs/lib.es2015.symbol.d.ts @@ -31,7 +31,7 @@ interface SymbolConstructor { * Otherwise, returns a new symbol with this key. * @param key key to search for. */ - for(key: string): symbol; + for(key: Key): RegisteredSymbol; /** * Returns a key from the global symbol registry matching the given Symbol if found. @@ -42,3 +42,5 @@ interface SymbolConstructor { } declare var Symbol: SymbolConstructor; + +type RegisteredSymbol = intrinsic; diff --git a/tsc/internal/checker/checker.go b/tsc/internal/checker/checker.go index 983fc751b03f8..40b567c35cc52 100644 --- a/tsc/internal/checker/checker.go +++ b/tsc/internal/checker/checker.go @@ -356,14 +356,16 @@ const ( IntrinsicTypeKindCapitalize IntrinsicTypeKindUncapitalize IntrinsicTypeKindNoInfer + IntrinsicTypeKindRegisteredSymbol ) var intrinsicTypeKinds = map[string]IntrinsicTypeKind{ - "Uppercase": IntrinsicTypeKindUppercase, - "Lowercase": IntrinsicTypeKindLowercase, - "Capitalize": IntrinsicTypeKindCapitalize, - "Uncapitalize": IntrinsicTypeKindUncapitalize, - "NoInfer": IntrinsicTypeKindNoInfer, + "Uppercase": IntrinsicTypeKindUppercase, + "Lowercase": IntrinsicTypeKindLowercase, + "Capitalize": IntrinsicTypeKindCapitalize, + "Uncapitalize": IntrinsicTypeKindUncapitalize, + "NoInfer": IntrinsicTypeKindNoInfer, + "RegisteredSymbol": IntrinsicTypeKindRegisteredSymbol, } type MappedTypeModifiers uint32 @@ -631,6 +633,7 @@ type Checker struct { indexedAccessTypes map[CacheHashKey]*Type templateLiteralTypes map[CacheHashKey]*Type stringMappingTypes map[StringMappingKey]*Type + registeredESSymbolTypes map[CacheHashKey]*Type uniqueESSymbolTypes map[*ast.Symbol]*Type thisExpandoKinds map[*ast.Symbol]thisAssignmentDeclarationKind thisExpandoLocations map[*ast.Symbol]*ast.Node @@ -947,6 +950,7 @@ func NewChecker(program Program, tracer *Tracer) (*Checker, *sync.Mutex) { c.indexedAccessTypes = make(map[CacheHashKey]*Type) c.templateLiteralTypes = make(map[CacheHashKey]*Type) c.stringMappingTypes = make(map[StringMappingKey]*Type) + c.registeredESSymbolTypes = make(map[CacheHashKey]*Type) c.uniqueESSymbolTypes = make(map[*ast.Symbol]*Type) c.thisExpandoKinds = make(map[*ast.Symbol]thisAssignmentDeclarationKind) c.thisExpandoLocations = make(map[*ast.Symbol]*ast.Node) @@ -7539,7 +7543,7 @@ func (c *Checker) getQuickTypeOfExpression(node *ast.Node) *Type { return nil // Optimize for the common case of a call to a function with a single non-generic call // signature where we can just fetch the return type without checking the arguments. - case ast.IsCallExpression(expr) && expr.Expression().Kind != ast.KindSuperKeyword && !ast.IsRequireCall(expr, true /*requireStringLiteralLikeArgument*/) && !c.isSymbolOrSymbolForCall(expr) && !ast.IsImportCall(expr): + case ast.IsCallExpression(expr) && expr.Expression().Kind != ast.KindSuperKeyword && !ast.IsRequireCall(expr, true /*requireStringLiteralLikeArgument*/) && !c.isSymbolCall(expr) && !ast.IsImportCall(expr): if isCallChain(expr) { return c.getReturnTypeOfSingleNonGenericSignatureOfCallChain(expr) } @@ -8519,7 +8523,7 @@ func (c *Checker) checkCallExpression(node *ast.Node, checkMode CheckMode) *Type returnType := c.getReturnTypeOfSignature(signature) // Treat any call to the global 'Symbol' function that is part of a const variable or readonly property // as a fresh unique symbol literal type. - if returnType.flags&TypeFlagsESSymbolLike != 0 && c.isSymbolOrSymbolForCall(node) { + if returnType.flags&TypeFlagsESSymbolLike != 0 && c.isSymbolCall(node) { return c.getESSymbolLikeTypeForNode(ast.WalkUpParenthesizedExpressions(node.Parent)) } if ast.IsCallExpression(node) && node.QuestionDotToken() == nil && ast.IsExpressionStatement(node.Parent) && returnType.flags&TypeFlagsVoid != 0 && c.getTypePredicateOfSignature(signature) != nil { @@ -8550,14 +8554,11 @@ func (c *Checker) addDeprecatedSuggestionWithSignature(location *ast.Node, decla return c.addDeprecatedSuggestionWorker([]*ast.Node{declaration}, diagnostic) } -func (c *Checker) isSymbolOrSymbolForCall(node *ast.Node) bool { +func (c *Checker) isSymbolCall(node *ast.Node) bool { if !ast.IsCallExpression(node) { return false } left := node.Expression() - if ast.IsPropertyAccessExpression(left) && left.Name().Text() == "for" { - left = left.Expression() - } if !ast.IsIdentifier(left) || left.Text() != "Symbol" { return false } @@ -18585,7 +18586,7 @@ func (c *Checker) widenTypeForVariableLikeDeclaration(t *Type, declaration *ast. } // always widen a 'unique symbol' type if the type was created for a different declaration. - if t.flags&TypeFlagsUniqueESSymbol != 0 && (ast.IsBindingElement(declaration) || declaration.Type() == nil) && t.symbol != c.getSymbolOfDeclaration(declaration) { + if t.flags&TypeFlagsUniqueESSymbol != 0 && !isRegisteredSymbolAlias(t.alias) && (ast.IsBindingElement(declaration) || declaration.Type() == nil) && t.symbol != c.getSymbolOfDeclaration(declaration) { t = c.esSymbolType } return c.getWidenedType(t) @@ -22629,6 +22630,9 @@ func (c *Checker) instantiateTypeWorker(t *Type, m *TypeMapper, alias *TypeAlias return c.getTemplateLiteralType(t.AsTemplateLiteralType().texts, c.instantiateTypes(t.AsTemplateLiteralType().types, m)) case flags&TypeFlagsStringMapping != 0: return c.getStringMappingType(t.symbol, c.instantiateType(t.AsStringMappingType().target, m)) + case flags&TypeFlagsUniqueESSymbol != 0 && isRegisteredSymbolAlias(t.alias): + newAlias := c.instantiateTypeAlias(t.alias, m) + return c.getRegisteredESSymbolType(newAlias.typeArguments[0], newAlias) case flags&TypeFlagsConditional != 0: return c.getConditionalTypeInstantiation(t, c.combineTypeMappers(t.AsConditionalType().mapper, m), false /*forConstraint*/, alias) case flags&TypeFlagsSubstitution != 0: @@ -22654,6 +22658,10 @@ func (c *Checker) instantiateTypeWorker(t *Type, m *TypeMapper, alias *TypeAlias return t } +func isRegisteredSymbolAlias(alias *TypeAlias) bool { + return alias != nil && alias.symbol != nil && alias.symbol.Name == "RegisteredSymbol" && len(alias.typeArguments) == 1 +} + // Handles instantiation of the following object types: // AnonymousType (ObjectFlagsAnonymous|ObjectFlagsSingleSignatureType) // TypeReference with node != nil (ObjectFlagsReference) @@ -23358,6 +23366,46 @@ func (c *Checker) getESSymbolLikeTypeForNode(node *ast.Node) *Type { return c.esSymbolType } +func (c *Checker) getRegisteredESSymbolType(keyType *Type, alias *TypeAlias) *Type { + key := c.getRegisteredESSymbolTypeKey(keyType) + t := c.registeredESSymbolTypes[key] + if t == nil { + name := ast.InternalSymbolNamePrefix + "@@" + c.getRegisteredESSymbolNameText(keyType) + symbol := c.newSymbol(ast.SymbolFlagsProperty, name) + t = c.newUniqueESSymbolType(symbol, name) + c.registeredESSymbolTypes[key] = t + } + t.alias = alias + return t +} + +func (c *Checker) getRegisteredESSymbolTypeKey(keyType *Type) CacheHashKey { + var b keyBuilder + b.writeString("RegisteredSymbol") + if keyType.flags&TypeFlagsStringLiteral != 0 { + b.writeByte('s') + b.writeString(getStringLiteralValue(keyType)) + } else if keyType.flags&TypeFlagsNumberLiteral != 0 { + b.writeByte('n') + b.writeString(getNumberLiteralValue(keyType).String()) + } else { + b.writeByte('t') + b.writeType(keyType) + } + return b.hash() +} + +func (c *Checker) getRegisteredESSymbolNameText(keyType *Type) string { + switch { + case keyType.flags&TypeFlagsStringLiteral != 0: + return getStringLiteralValue(keyType) + case keyType.flags&TypeFlagsNumberLiteral != 0: + return getNumberLiteralValue(keyType).String() + default: + return c.typeToStringEx(keyType, nil, TypeFormatFlagsNoTruncation|TypeFormatFlagsUseAliasDefinedOutsideCurrentScope, nil) + } +} + func (c *Checker) getTypeFromTypeReference(node *ast.Node) *Type { links := c.typeNodeLinks.Get(node) if links.resolvedType == nil { @@ -24039,6 +24087,11 @@ func (c *Checker) getTypeAliasInstantiation(symbol *ast.Symbol, typeArguments [] switch typeKind { case IntrinsicTypeKindNoInfer: return c.getNoInferType(typeArguments[0]) + case IntrinsicTypeKindRegisteredSymbol: + if alias == nil { + alias = &TypeAlias{symbol: symbol, typeArguments: typeArguments} + } + return c.getRegisteredESSymbolType(typeArguments[0], alias) default: return c.getStringMappingType(symbol, typeArguments[0]) } diff --git a/tsc/internal/checker/nodebuilderimpl.go b/tsc/internal/checker/nodebuilderimpl.go index 5cd58f6ec95f0..9c7db3bd855e3 100644 --- a/tsc/internal/checker/nodebuilderimpl.go +++ b/tsc/internal/checker/nodebuilderimpl.go @@ -2568,6 +2568,11 @@ func (b *NodeBuilderImpl) getPropertyNameNodeForSymbolFromNameType(symbol *ast.S return b.createPropertyNameNodeForIdentifierOrLiteral(name, singleQuote, stringNamed, isMethod, symbol) } if nameType.flags&TypeFlagsUniqueESSymbol != 0 { + if isRegisteredSymbolAlias(nameType.alias) && symbol.ValueDeclaration != nil { + if declName := symbol.ValueDeclaration.Name(); declName != nil && ast.IsComputedPropertyName(declName) { + return b.f.DeepCloneNode(declName) + } + } // The reference was tracked in the destination scope by trackComputedName. // Reconstructing its spelling in the source scope must not paint that scope's declarations visible. return b.f.NewComputedPropertyName(b.symbolToExpressionWorker(nameType.AsUniqueESSymbolType().symbol, ast.SymbolFlagsValue)) @@ -3409,6 +3414,9 @@ func (b *NodeBuilderImpl) typeToTypeNode(t *Type) *ast.TypeNode { } } if t.flags&TypeFlagsUniqueESSymbol != 0 { + if isRegisteredSymbolAlias(t.alias) { + return t.alias.ToTypeReferenceNode(b) + } if b.ctx.flags&nodebuilder.FlagsAllowUniqueESSymbolType == 0 { if b.ch.IsValueSymbolAccessible(t.symbol, b.ctx.enclosingDeclaration) { b.ctx.approximateLength += 6 From 5865d6ae6f0639aa8fa6cb5b02036ac648ad5c4c Mon Sep 17 00:00:00 2001 From: Michael FIG Date: Mon, 10 Aug 2026 14:23:12 -0600 Subject: [PATCH 2/6] Propagate a narrow `unique symbol` as if `const` --- .../uniqueSymbolConstLikeWidening.symbols | 40 +++++++++++++++++++ .../uniqueSymbolConstLikeWidening.types | 40 +++++++++++++++++++ .../compiler/uniqueSymbolConstLikeWidening.ts | 12 ++++++ tsc/internal/checker/checker.go | 13 ++++-- 4 files changed, 102 insertions(+), 3 deletions(-) create mode 100644 testdata/baselines/reference/compiler/uniqueSymbolConstLikeWidening.symbols create mode 100644 testdata/baselines/reference/compiler/uniqueSymbolConstLikeWidening.types create mode 100644 testdata/tests/cases/compiler/uniqueSymbolConstLikeWidening.ts diff --git a/testdata/baselines/reference/compiler/uniqueSymbolConstLikeWidening.symbols b/testdata/baselines/reference/compiler/uniqueSymbolConstLikeWidening.symbols new file mode 100644 index 0000000000000..1aac2b9272522 --- /dev/null +++ b/testdata/baselines/reference/compiler/uniqueSymbolConstLikeWidening.symbols @@ -0,0 +1,40 @@ +//// [tests/cases/compiler/uniqueSymbolConstLikeWidening.ts] //// + +=== uniqueSymbolConstLikeWidening.ts === +const us = Symbol.match; +>us : Symbol(us, Decl(uniqueSymbolConstLikeWidening.ts, 0, 5)) +>Symbol.match : Symbol(SymbolConstructor.match, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>match : Symbol(SymbolConstructor.match, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + +const us2 = us; +>us2 : Symbol(us2, Decl(uniqueSymbolConstLikeWidening.ts, 1, 5)) +>us : Symbol(us, Decl(uniqueSymbolConstLikeWidening.ts, 0, 5)) + +let widened = us; +>widened : Symbol(widened, Decl(uniqueSymbolConstLikeWidening.ts, 2, 3)) +>us : Symbol(us, Decl(uniqueSymbolConstLikeWidening.ts, 0, 5)) + +let asserted = us as const; +>asserted : Symbol(asserted, Decl(uniqueSymbolConstLikeWidening.ts, 3, 3)) +>us : Symbol(us, Decl(uniqueSymbolConstLikeWidening.ts, 0, 5)) +>const : Symbol(const) + +let sameAsSource: typeof us = us2; +>sameAsSource : Symbol(sameAsSource, Decl(uniqueSymbolConstLikeWidening.ts, 5, 3)) +>us : Symbol(us, Decl(uniqueSymbolConstLikeWidening.ts, 0, 5)) +>us2 : Symbol(us2, Decl(uniqueSymbolConstLikeWidening.ts, 1, 5)) + +let sameAsAsserted: typeof us = asserted; +>sameAsAsserted : Symbol(sameAsAsserted, Decl(uniqueSymbolConstLikeWidening.ts, 6, 3)) +>us : Symbol(us, Decl(uniqueSymbolConstLikeWidening.ts, 0, 5)) +>asserted : Symbol(asserted, Decl(uniqueSymbolConstLikeWidening.ts, 3, 3)) + +let symbolFromConst: symbol = us2; +>symbolFromConst : Symbol(symbolFromConst, Decl(uniqueSymbolConstLikeWidening.ts, 7, 3)) +>us2 : Symbol(us2, Decl(uniqueSymbolConstLikeWidening.ts, 1, 5)) + +let symbolFromAsserted: symbol = asserted; +>symbolFromAsserted : Symbol(symbolFromAsserted, Decl(uniqueSymbolConstLikeWidening.ts, 8, 3)) +>asserted : Symbol(asserted, Decl(uniqueSymbolConstLikeWidening.ts, 3, 3)) + diff --git a/testdata/baselines/reference/compiler/uniqueSymbolConstLikeWidening.types b/testdata/baselines/reference/compiler/uniqueSymbolConstLikeWidening.types new file mode 100644 index 0000000000000..98d7ed64ab4d0 --- /dev/null +++ b/testdata/baselines/reference/compiler/uniqueSymbolConstLikeWidening.types @@ -0,0 +1,40 @@ +//// [tests/cases/compiler/uniqueSymbolConstLikeWidening.ts] //// + +=== uniqueSymbolConstLikeWidening.ts === +const us = Symbol.match; +>us : unique symbol +>Symbol.match : unique symbol +>Symbol : SymbolConstructor +>match : unique symbol + +const us2 = us; +>us2 : unique symbol +>us : unique symbol + +let widened = us; +>widened : symbol +>us : unique symbol + +let asserted = us as const; +>asserted : unique symbol +>us as const : unique symbol +>us : unique symbol + +let sameAsSource: typeof us = us2; +>sameAsSource : unique symbol +>us : unique symbol +>us2 : unique symbol + +let sameAsAsserted: typeof us = asserted; +>sameAsAsserted : unique symbol +>us : unique symbol +>asserted : unique symbol + +let symbolFromConst: symbol = us2; +>symbolFromConst : symbol +>us2 : unique symbol + +let symbolFromAsserted: symbol = asserted; +>symbolFromAsserted : symbol +>asserted : unique symbol + diff --git a/testdata/tests/cases/compiler/uniqueSymbolConstLikeWidening.ts b/testdata/tests/cases/compiler/uniqueSymbolConstLikeWidening.ts new file mode 100644 index 0000000000000..c7314629926cd --- /dev/null +++ b/testdata/tests/cases/compiler/uniqueSymbolConstLikeWidening.ts @@ -0,0 +1,12 @@ +// @target: es2015 +// @noEmit: true + +const us = Symbol.match; +const us2 = us; +let widened = us; +let asserted = us as const; + +let sameAsSource: typeof us = us2; +let sameAsAsserted: typeof us = asserted; +let symbolFromConst: symbol = us2; +let symbolFromAsserted: symbol = asserted; diff --git a/tsc/internal/checker/checker.go b/tsc/internal/checker/checker.go index 40b567c35cc52..0d7e12da4e80f 100644 --- a/tsc/internal/checker/checker.go +++ b/tsc/internal/checker/checker.go @@ -12502,7 +12502,7 @@ func (c *Checker) checkAssertion(node *ast.Node, checkMode CheckMode) *Type { // safe even for `x as const` and keeps diagnostics stable regardless of traversal order. c.checkSourceElement(typeNode) if isConstTypeReference(typeNode) { - if !c.isValidConstAssertionArgument(node.Expression()) { + if !c.isValidConstAssertionArgument(node.Expression()) && exprType.flags&TypeFlagsUniqueESSymbol == 0 { c.error(node.Expression(), diagnostics.A_const_assertion_can_only_be_applied_to_references_to_enum_members_or_string_number_boolean_array_or_object_literals) } return c.getRegularTypeOfLiteralType(exprType) @@ -18585,8 +18585,9 @@ func (c *Checker) widenTypeForVariableLikeDeclaration(t *Type, declaration *ast. c.reportErrorsFromWidening(declaration, t, WideningKindNormal) } - // always widen a 'unique symbol' type if the type was created for a different declaration. - if t.flags&TypeFlagsUniqueESSymbol != 0 && !isRegisteredSymbolAlias(t.alias) && (ast.IsBindingElement(declaration) || declaration.Type() == nil) && t.symbol != c.getSymbolOfDeclaration(declaration) { + // Widen a 'unique symbol' type if the type was created for a different declaration, unless the + // declaration or initializer is const-like. + if t.flags&TypeFlagsUniqueESSymbol != 0 && !c.isConstLikeUniqueSymbolDeclaration(declaration) && (ast.IsBindingElement(declaration) || declaration.Type() == nil) && t.symbol != c.getSymbolOfDeclaration(declaration) { t = c.esSymbolType } return c.getWidenedType(t) @@ -18606,6 +18607,12 @@ func (c *Checker) widenTypeForVariableLikeDeclaration(t *Type, declaration *ast. return t } +func (c *Checker) isConstLikeUniqueSymbolDeclaration(declaration *ast.Node) bool { + return c.getCombinedNodeFlagsCached(declaration)&ast.NodeFlagsConstant != 0 || + isDeclarationReadonly(declaration) || + declaration.Initializer() != nil && ast.IsConstAssertion(ast.SkipParentheses(declaration.Initializer())) +} + func (c *Checker) reportImplicitAny(declaration *ast.Node, t *Type, wideningKind WideningKind) { if ast.IsInJSFile(declaration) && !ast.IsCheckJSEnabledForFile(ast.GetSourceFileOfNode(declaration), c.compilerOptions) { // Only report implicit any errors/suggestions in TS and ts-check JS files From 99187cdbc3444c8dbe426a236cbe332b1f39d531 Mon Sep 17 00:00:00 2001 From: Michael FIG Date: Mon, 10 Aug 2026 15:06:25 -0600 Subject: [PATCH 3/6] Verify symbol-keyed object property access --- .../registeredSymbolPropertyAccess.js | 95 ++++++ .../registeredSymbolPropertyAccess.symbols | 206 +++++++++++++ .../registeredSymbolPropertyAccess.types | 275 ++++++++++++++++++ .../registeredSymbolPropertyAccess.ts | 54 ++++ 4 files changed, 630 insertions(+) create mode 100644 testdata/baselines/reference/compiler/registeredSymbolPropertyAccess.js create mode 100644 testdata/baselines/reference/compiler/registeredSymbolPropertyAccess.symbols create mode 100644 testdata/baselines/reference/compiler/registeredSymbolPropertyAccess.types create mode 100644 testdata/tests/cases/compiler/registeredSymbolPropertyAccess.ts diff --git a/testdata/baselines/reference/compiler/registeredSymbolPropertyAccess.js b/testdata/baselines/reference/compiler/registeredSymbolPropertyAccess.js new file mode 100644 index 0000000000000..857c76270a09f --- /dev/null +++ b/testdata/baselines/reference/compiler/registeredSymbolPropertyAccess.js @@ -0,0 +1,95 @@ +//// [tests/cases/compiler/registeredSymbolPropertyAccess.ts] //// + +//// [registeredSymbolPropertyAccess.ts] +export const single = Symbol.for("single"); +export const twin1 = Symbol.for("twin"); +export const twin2 = Symbol.for("twin"); +export const unique1 = Symbol("unique"); +export const unique2 = Symbol("unique"); +export const wellKnown = Symbol.match; +export const wellKnown2 = Symbol.toStringTag; + +export const record1 = { + [single]: "single", + [twin2]: "twin", + [unique1]: "unique1", + [unique2]: "unique2", +} as const; +export let singleVal: string = record1[single] satisfies "single"; +export let twin1Val: string = record1[twin1] satisfies "twin"; +export let twin2Val: string = record1[twin2] satisfies "twin"; +export let unique1Val: string = record1[unique1] satisfies "unique1"; +export let unique2Val: string = record1[unique2] satisfies "unique2"; + +export const record2 = { + ...record1, + [unique1]: "unique1New", + [wellKnown]: "wellKnown", +} as const; +singleVal = record2[single] satisfies "single"; +twin1Val = record2[twin1] satisfies "twin"; +twin2Val = record2[twin2] satisfies "twin"; +unique1Val = record2[unique1] satisfies "unique1New"; +unique2Val = record2[unique2] satisfies "unique2"; +export let wellKnownVal: string = record2[wellKnown] satisfies "wellKnown"; + +export const record3 = { + [single]: "single", + [twin2]: "twin", + [unique1]: "unique1", + [unique2]: "unique2", + [wellKnown]: "wellKnown", +} as const; +singleVal = record3[single] satisfies "single"; +twin1Val = record3[twin1] satisfies "twin"; +twin2Val = record3[twin2] satisfies "twin"; +unique1Val = record3[unique1] satisfies "unique1"; +unique2Val = record3[unique2] satisfies "unique2"; +wellKnownVal = record3[wellKnown] satisfies "wellKnown"; + +export const record4 = { + [wellKnown2]: "wellKnown2", +} as const; +export let wellKnown2Val: string = record4[wellKnown2] satisfies "wellKnown2"; + + + + +//// [registeredSymbolPropertyAccess.d.ts] +export declare const single: RegisteredSymbol<"single">; +export declare const twin1: RegisteredSymbol<"twin">; +export declare const twin2: RegisteredSymbol<"twin">; +export declare const unique1: unique symbol; +export declare const unique2: unique symbol; +export declare const wellKnown: typeof Symbol.match; +export declare const wellKnown2: typeof Symbol.toStringTag; +export declare const record1: { + readonly [single]: "single"; + readonly [twin2]: "twin"; + readonly [unique1]: "unique1"; + readonly [unique2]: "unique2"; +}; +export declare let singleVal: string; +export declare let twin1Val: string; +export declare let twin2Val: string; +export declare let unique1Val: string; +export declare let unique2Val: string; +export declare const record2: { + readonly [single]: "single"; + readonly [twin2]: "twin"; + readonly [unique2]: "unique2"; + readonly [unique1]: "unique1New"; + readonly [Symbol.match]: "wellKnown"; +}; +export declare let wellKnownVal: string; +export declare const record3: { + readonly [single]: "single"; + readonly [twin2]: "twin"; + readonly [unique1]: "unique1"; + readonly [unique2]: "unique2"; + readonly [Symbol.match]: "wellKnown"; +}; +export declare const record4: { + readonly [Symbol.toStringTag]: "wellKnown2"; +}; +export declare let wellKnown2Val: string; diff --git a/testdata/baselines/reference/compiler/registeredSymbolPropertyAccess.symbols b/testdata/baselines/reference/compiler/registeredSymbolPropertyAccess.symbols new file mode 100644 index 0000000000000..e35b0562a5d73 --- /dev/null +++ b/testdata/baselines/reference/compiler/registeredSymbolPropertyAccess.symbols @@ -0,0 +1,206 @@ +//// [tests/cases/compiler/registeredSymbolPropertyAccess.ts] //// + +=== registeredSymbolPropertyAccess.ts === +export const single = Symbol.for("single"); +>single : Symbol(single, Decl(registeredSymbolPropertyAccess.ts, 0, 12)) +>Symbol.for : Symbol(SymbolConstructor.for, Decl(lib.es2015.symbol.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>for : Symbol(SymbolConstructor.for, Decl(lib.es2015.symbol.d.ts, --, --)) + +export const twin1 = Symbol.for("twin"); +>twin1 : Symbol(twin1, Decl(registeredSymbolPropertyAccess.ts, 1, 12)) +>Symbol.for : Symbol(SymbolConstructor.for, Decl(lib.es2015.symbol.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>for : Symbol(SymbolConstructor.for, Decl(lib.es2015.symbol.d.ts, --, --)) + +export const twin2 = Symbol.for("twin"); +>twin2 : Symbol(twin2, Decl(registeredSymbolPropertyAccess.ts, 2, 12)) +>Symbol.for : Symbol(SymbolConstructor.for, Decl(lib.es2015.symbol.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>for : Symbol(SymbolConstructor.for, Decl(lib.es2015.symbol.d.ts, --, --)) + +export const unique1 = Symbol("unique"); +>unique1 : Symbol(unique1, Decl(registeredSymbolPropertyAccess.ts, 3, 12)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + +export const unique2 = Symbol("unique"); +>unique2 : Symbol(unique2, Decl(registeredSymbolPropertyAccess.ts, 4, 12)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + +export const wellKnown = Symbol.match; +>wellKnown : Symbol(wellKnown, Decl(registeredSymbolPropertyAccess.ts, 5, 12)) +>Symbol.match : Symbol(SymbolConstructor.match, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>match : Symbol(SymbolConstructor.match, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + +export const wellKnown2 = Symbol.toStringTag; +>wellKnown2 : Symbol(wellKnown2, Decl(registeredSymbolPropertyAccess.ts, 6, 12)) +>Symbol.toStringTag : Symbol(SymbolConstructor.toStringTag, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>toStringTag : Symbol(SymbolConstructor.toStringTag, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + +export const record1 = { +>record1 : Symbol(record1, Decl(registeredSymbolPropertyAccess.ts, 8, 12)) + + [single]: "single", +>[single] : Symbol([single], Decl(registeredSymbolPropertyAccess.ts, 8, 24)) +>single : Symbol(single, Decl(registeredSymbolPropertyAccess.ts, 0, 12)) + + [twin2]: "twin", +>[twin2] : Symbol([twin2], Decl(registeredSymbolPropertyAccess.ts, 9, 23)) +>twin2 : Symbol(twin2, Decl(registeredSymbolPropertyAccess.ts, 2, 12)) + + [unique1]: "unique1", +>[unique1] : Symbol([unique1], Decl(registeredSymbolPropertyAccess.ts, 10, 20)) +>unique1 : Symbol(unique1, Decl(registeredSymbolPropertyAccess.ts, 3, 12)) + + [unique2]: "unique2", +>[unique2] : Symbol([unique2], Decl(registeredSymbolPropertyAccess.ts, 11, 25)) +>unique2 : Symbol(unique2, Decl(registeredSymbolPropertyAccess.ts, 4, 12)) + +} as const; +>const : Symbol(const) + +export let singleVal: string = record1[single] satisfies "single"; +>singleVal : Symbol(singleVal, Decl(registeredSymbolPropertyAccess.ts, 14, 10)) +>record1 : Symbol(record1, Decl(registeredSymbolPropertyAccess.ts, 8, 12)) +>single : Symbol(single, Decl(registeredSymbolPropertyAccess.ts, 0, 12)) + +export let twin1Val: string = record1[twin1] satisfies "twin"; +>twin1Val : Symbol(twin1Val, Decl(registeredSymbolPropertyAccess.ts, 15, 10)) +>record1 : Symbol(record1, Decl(registeredSymbolPropertyAccess.ts, 8, 12)) +>twin1 : Symbol(twin1, Decl(registeredSymbolPropertyAccess.ts, 1, 12)) + +export let twin2Val: string = record1[twin2] satisfies "twin"; +>twin2Val : Symbol(twin2Val, Decl(registeredSymbolPropertyAccess.ts, 16, 10)) +>record1 : Symbol(record1, Decl(registeredSymbolPropertyAccess.ts, 8, 12)) +>twin2 : Symbol(twin2, Decl(registeredSymbolPropertyAccess.ts, 2, 12)) + +export let unique1Val: string = record1[unique1] satisfies "unique1"; +>unique1Val : Symbol(unique1Val, Decl(registeredSymbolPropertyAccess.ts, 17, 10)) +>record1 : Symbol(record1, Decl(registeredSymbolPropertyAccess.ts, 8, 12)) +>unique1 : Symbol(unique1, Decl(registeredSymbolPropertyAccess.ts, 3, 12)) + +export let unique2Val: string = record1[unique2] satisfies "unique2"; +>unique2Val : Symbol(unique2Val, Decl(registeredSymbolPropertyAccess.ts, 18, 10)) +>record1 : Symbol(record1, Decl(registeredSymbolPropertyAccess.ts, 8, 12)) +>unique2 : Symbol(unique2, Decl(registeredSymbolPropertyAccess.ts, 4, 12)) + +export const record2 = { +>record2 : Symbol(record2, Decl(registeredSymbolPropertyAccess.ts, 20, 12)) + + ...record1, +>record1 : Symbol(record1, Decl(registeredSymbolPropertyAccess.ts, 8, 12)) + + [unique1]: "unique1New", +>[unique1] : Symbol([unique1], Decl(registeredSymbolPropertyAccess.ts, 21, 15)) +>unique1 : Symbol(unique1, Decl(registeredSymbolPropertyAccess.ts, 3, 12)) + + [wellKnown]: "wellKnown", +>[wellKnown] : Symbol([wellKnown], Decl(registeredSymbolPropertyAccess.ts, 22, 28)) +>wellKnown : Symbol(wellKnown, Decl(registeredSymbolPropertyAccess.ts, 5, 12)) + +} as const; +>const : Symbol(const) + +singleVal = record2[single] satisfies "single"; +>singleVal : Symbol(singleVal, Decl(registeredSymbolPropertyAccess.ts, 14, 10)) +>record2 : Symbol(record2, Decl(registeredSymbolPropertyAccess.ts, 20, 12)) +>single : Symbol(single, Decl(registeredSymbolPropertyAccess.ts, 0, 12)) + +twin1Val = record2[twin1] satisfies "twin"; +>twin1Val : Symbol(twin1Val, Decl(registeredSymbolPropertyAccess.ts, 15, 10)) +>record2 : Symbol(record2, Decl(registeredSymbolPropertyAccess.ts, 20, 12)) +>twin1 : Symbol(twin1, Decl(registeredSymbolPropertyAccess.ts, 1, 12)) + +twin2Val = record2[twin2] satisfies "twin"; +>twin2Val : Symbol(twin2Val, Decl(registeredSymbolPropertyAccess.ts, 16, 10)) +>record2 : Symbol(record2, Decl(registeredSymbolPropertyAccess.ts, 20, 12)) +>twin2 : Symbol(twin2, Decl(registeredSymbolPropertyAccess.ts, 2, 12)) + +unique1Val = record2[unique1] satisfies "unique1New"; +>unique1Val : Symbol(unique1Val, Decl(registeredSymbolPropertyAccess.ts, 17, 10)) +>record2 : Symbol(record2, Decl(registeredSymbolPropertyAccess.ts, 20, 12)) +>unique1 : Symbol(unique1, Decl(registeredSymbolPropertyAccess.ts, 3, 12)) + +unique2Val = record2[unique2] satisfies "unique2"; +>unique2Val : Symbol(unique2Val, Decl(registeredSymbolPropertyAccess.ts, 18, 10)) +>record2 : Symbol(record2, Decl(registeredSymbolPropertyAccess.ts, 20, 12)) +>unique2 : Symbol(unique2, Decl(registeredSymbolPropertyAccess.ts, 4, 12)) + +export let wellKnownVal: string = record2[wellKnown] satisfies "wellKnown"; +>wellKnownVal : Symbol(wellKnownVal, Decl(registeredSymbolPropertyAccess.ts, 30, 10)) +>record2 : Symbol(record2, Decl(registeredSymbolPropertyAccess.ts, 20, 12)) +>wellKnown : Symbol(wellKnown, Decl(registeredSymbolPropertyAccess.ts, 5, 12)) + +export const record3 = { +>record3 : Symbol(record3, Decl(registeredSymbolPropertyAccess.ts, 32, 12)) + + [single]: "single", +>[single] : Symbol([single], Decl(registeredSymbolPropertyAccess.ts, 32, 24)) +>single : Symbol(single, Decl(registeredSymbolPropertyAccess.ts, 0, 12)) + + [twin2]: "twin", +>[twin2] : Symbol([twin2], Decl(registeredSymbolPropertyAccess.ts, 33, 23)) +>twin2 : Symbol(twin2, Decl(registeredSymbolPropertyAccess.ts, 2, 12)) + + [unique1]: "unique1", +>[unique1] : Symbol([unique1], Decl(registeredSymbolPropertyAccess.ts, 34, 20)) +>unique1 : Symbol(unique1, Decl(registeredSymbolPropertyAccess.ts, 3, 12)) + + [unique2]: "unique2", +>[unique2] : Symbol([unique2], Decl(registeredSymbolPropertyAccess.ts, 35, 25)) +>unique2 : Symbol(unique2, Decl(registeredSymbolPropertyAccess.ts, 4, 12)) + + [wellKnown]: "wellKnown", +>[wellKnown] : Symbol([wellKnown], Decl(registeredSymbolPropertyAccess.ts, 36, 25)) +>wellKnown : Symbol(wellKnown, Decl(registeredSymbolPropertyAccess.ts, 5, 12)) + +} as const; +>const : Symbol(const) + +singleVal = record3[single] satisfies "single"; +>singleVal : Symbol(singleVal, Decl(registeredSymbolPropertyAccess.ts, 14, 10)) +>record3 : Symbol(record3, Decl(registeredSymbolPropertyAccess.ts, 32, 12)) +>single : Symbol(single, Decl(registeredSymbolPropertyAccess.ts, 0, 12)) + +twin1Val = record3[twin1] satisfies "twin"; +>twin1Val : Symbol(twin1Val, Decl(registeredSymbolPropertyAccess.ts, 15, 10)) +>record3 : Symbol(record3, Decl(registeredSymbolPropertyAccess.ts, 32, 12)) +>twin1 : Symbol(twin1, Decl(registeredSymbolPropertyAccess.ts, 1, 12)) + +twin2Val = record3[twin2] satisfies "twin"; +>twin2Val : Symbol(twin2Val, Decl(registeredSymbolPropertyAccess.ts, 16, 10)) +>record3 : Symbol(record3, Decl(registeredSymbolPropertyAccess.ts, 32, 12)) +>twin2 : Symbol(twin2, Decl(registeredSymbolPropertyAccess.ts, 2, 12)) + +unique1Val = record3[unique1] satisfies "unique1"; +>unique1Val : Symbol(unique1Val, Decl(registeredSymbolPropertyAccess.ts, 17, 10)) +>record3 : Symbol(record3, Decl(registeredSymbolPropertyAccess.ts, 32, 12)) +>unique1 : Symbol(unique1, Decl(registeredSymbolPropertyAccess.ts, 3, 12)) + +unique2Val = record3[unique2] satisfies "unique2"; +>unique2Val : Symbol(unique2Val, Decl(registeredSymbolPropertyAccess.ts, 18, 10)) +>record3 : Symbol(record3, Decl(registeredSymbolPropertyAccess.ts, 32, 12)) +>unique2 : Symbol(unique2, Decl(registeredSymbolPropertyAccess.ts, 4, 12)) + +wellKnownVal = record3[wellKnown] satisfies "wellKnown"; +>wellKnownVal : Symbol(wellKnownVal, Decl(registeredSymbolPropertyAccess.ts, 30, 10)) +>record3 : Symbol(record3, Decl(registeredSymbolPropertyAccess.ts, 32, 12)) +>wellKnown : Symbol(wellKnown, Decl(registeredSymbolPropertyAccess.ts, 5, 12)) + +export const record4 = { +>record4 : Symbol(record4, Decl(registeredSymbolPropertyAccess.ts, 46, 12)) + + [wellKnown2]: "wellKnown2", +>[wellKnown2] : Symbol([wellKnown2], Decl(registeredSymbolPropertyAccess.ts, 46, 24)) +>wellKnown2 : Symbol(wellKnown2, Decl(registeredSymbolPropertyAccess.ts, 6, 12)) + +} as const; +>const : Symbol(const) + +export let wellKnown2Val: string = record4[wellKnown2] satisfies "wellKnown2"; +>wellKnown2Val : Symbol(wellKnown2Val, Decl(registeredSymbolPropertyAccess.ts, 49, 10)) +>record4 : Symbol(record4, Decl(registeredSymbolPropertyAccess.ts, 46, 12)) +>wellKnown2 : Symbol(wellKnown2, Decl(registeredSymbolPropertyAccess.ts, 6, 12)) + diff --git a/testdata/baselines/reference/compiler/registeredSymbolPropertyAccess.types b/testdata/baselines/reference/compiler/registeredSymbolPropertyAccess.types new file mode 100644 index 0000000000000..69ad18465418a --- /dev/null +++ b/testdata/baselines/reference/compiler/registeredSymbolPropertyAccess.types @@ -0,0 +1,275 @@ +//// [tests/cases/compiler/registeredSymbolPropertyAccess.ts] //// + +=== registeredSymbolPropertyAccess.ts === +export const single = Symbol.for("single"); +>single : RegisteredSymbol<"single"> +>Symbol.for("single") : RegisteredSymbol<"single"> +>Symbol.for : (key: Key) => RegisteredSymbol +>Symbol : SymbolConstructor +>for : (key: Key) => RegisteredSymbol +>"single" : "single" + +export const twin1 = Symbol.for("twin"); +>twin1 : RegisteredSymbol<"twin"> +>Symbol.for("twin") : RegisteredSymbol<"twin"> +>Symbol.for : (key: Key) => RegisteredSymbol +>Symbol : SymbolConstructor +>for : (key: Key) => RegisteredSymbol +>"twin" : "twin" + +export const twin2 = Symbol.for("twin"); +>twin2 : RegisteredSymbol<"twin"> +>Symbol.for("twin") : RegisteredSymbol<"twin"> +>Symbol.for : (key: Key) => RegisteredSymbol +>Symbol : SymbolConstructor +>for : (key: Key) => RegisteredSymbol +>"twin" : "twin" + +export const unique1 = Symbol("unique"); +>unique1 : unique symbol +>Symbol("unique") : unique symbol +>Symbol : SymbolConstructor +>"unique" : "unique" + +export const unique2 = Symbol("unique"); +>unique2 : unique symbol +>Symbol("unique") : unique symbol +>Symbol : SymbolConstructor +>"unique" : "unique" + +export const wellKnown = Symbol.match; +>wellKnown : unique symbol +>Symbol.match : unique symbol +>Symbol : SymbolConstructor +>match : unique symbol + +export const wellKnown2 = Symbol.toStringTag; +>wellKnown2 : unique symbol +>Symbol.toStringTag : unique symbol +>Symbol : SymbolConstructor +>toStringTag : unique symbol + +export const record1 = { +>record1 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique1]: "unique1"; readonly [unique2]: "unique2"; } +>{ [single]: "single", [twin2]: "twin", [unique1]: "unique1", [unique2]: "unique2",} as const : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique1]: "unique1"; readonly [unique2]: "unique2"; } +>{ [single]: "single", [twin2]: "twin", [unique1]: "unique1", [unique2]: "unique2",} : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique1]: "unique1"; readonly [unique2]: "unique2"; } + + [single]: "single", +>[single] : "single" +>single : RegisteredSymbol<"single"> +>"single" : "single" + + [twin2]: "twin", +>[twin2] : "twin" +>twin2 : RegisteredSymbol<"twin"> +>"twin" : "twin" + + [unique1]: "unique1", +>[unique1] : "unique1" +>unique1 : unique symbol +>"unique1" : "unique1" + + [unique2]: "unique2", +>[unique2] : "unique2" +>unique2 : unique symbol +>"unique2" : "unique2" + +} as const; +export let singleVal: string = record1[single] satisfies "single"; +>singleVal : string +>record1[single] satisfies "single" : "single" +>record1[single] : "single" +>record1 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique1]: "unique1"; readonly [unique2]: "unique2"; } +>single : RegisteredSymbol<"single"> + +export let twin1Val: string = record1[twin1] satisfies "twin"; +>twin1Val : string +>record1[twin1] satisfies "twin" : "twin" +>record1[twin1] : "twin" +>record1 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique1]: "unique1"; readonly [unique2]: "unique2"; } +>twin1 : RegisteredSymbol<"twin"> + +export let twin2Val: string = record1[twin2] satisfies "twin"; +>twin2Val : string +>record1[twin2] satisfies "twin" : "twin" +>record1[twin2] : "twin" +>record1 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique1]: "unique1"; readonly [unique2]: "unique2"; } +>twin2 : RegisteredSymbol<"twin"> + +export let unique1Val: string = record1[unique1] satisfies "unique1"; +>unique1Val : string +>record1[unique1] satisfies "unique1" : "unique1" +>record1[unique1] : "unique1" +>record1 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique1]: "unique1"; readonly [unique2]: "unique2"; } +>unique1 : unique symbol + +export let unique2Val: string = record1[unique2] satisfies "unique2"; +>unique2Val : string +>record1[unique2] satisfies "unique2" : "unique2" +>record1[unique2] : "unique2" +>record1 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique1]: "unique1"; readonly [unique2]: "unique2"; } +>unique2 : unique symbol + +export const record2 = { +>record2 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique2]: "unique2"; readonly [unique1]: "unique1New"; readonly [Symbol.match]: "wellKnown"; } +>{ ...record1, [unique1]: "unique1New", [wellKnown]: "wellKnown",} as const : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique2]: "unique2"; readonly [unique1]: "unique1New"; readonly [Symbol.match]: "wellKnown"; } +>{ ...record1, [unique1]: "unique1New", [wellKnown]: "wellKnown",} : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique2]: "unique2"; readonly [unique1]: "unique1New"; readonly [Symbol.match]: "wellKnown"; } + + ...record1, +>record1 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique1]: "unique1"; readonly [unique2]: "unique2"; } + + [unique1]: "unique1New", +>[unique1] : "unique1New" +>unique1 : unique symbol +>"unique1New" : "unique1New" + + [wellKnown]: "wellKnown", +>[wellKnown] : "wellKnown" +>wellKnown : unique symbol +>"wellKnown" : "wellKnown" + +} as const; +singleVal = record2[single] satisfies "single"; +>singleVal = record2[single] satisfies "single" : "single" +>singleVal : string +>record2[single] satisfies "single" : "single" +>record2[single] : "single" +>record2 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique2]: "unique2"; readonly [unique1]: "unique1New"; readonly [Symbol.match]: "wellKnown"; } +>single : RegisteredSymbol<"single"> + +twin1Val = record2[twin1] satisfies "twin"; +>twin1Val = record2[twin1] satisfies "twin" : "twin" +>twin1Val : string +>record2[twin1] satisfies "twin" : "twin" +>record2[twin1] : "twin" +>record2 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique2]: "unique2"; readonly [unique1]: "unique1New"; readonly [Symbol.match]: "wellKnown"; } +>twin1 : RegisteredSymbol<"twin"> + +twin2Val = record2[twin2] satisfies "twin"; +>twin2Val = record2[twin2] satisfies "twin" : "twin" +>twin2Val : string +>record2[twin2] satisfies "twin" : "twin" +>record2[twin2] : "twin" +>record2 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique2]: "unique2"; readonly [unique1]: "unique1New"; readonly [Symbol.match]: "wellKnown"; } +>twin2 : RegisteredSymbol<"twin"> + +unique1Val = record2[unique1] satisfies "unique1New"; +>unique1Val = record2[unique1] satisfies "unique1New" : "unique1New" +>unique1Val : string +>record2[unique1] satisfies "unique1New" : "unique1New" +>record2[unique1] : "unique1New" +>record2 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique2]: "unique2"; readonly [unique1]: "unique1New"; readonly [Symbol.match]: "wellKnown"; } +>unique1 : unique symbol + +unique2Val = record2[unique2] satisfies "unique2"; +>unique2Val = record2[unique2] satisfies "unique2" : "unique2" +>unique2Val : string +>record2[unique2] satisfies "unique2" : "unique2" +>record2[unique2] : "unique2" +>record2 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique2]: "unique2"; readonly [unique1]: "unique1New"; readonly [Symbol.match]: "wellKnown"; } +>unique2 : unique symbol + +export let wellKnownVal: string = record2[wellKnown] satisfies "wellKnown"; +>wellKnownVal : string +>record2[wellKnown] satisfies "wellKnown" : "wellKnown" +>record2[wellKnown] : "wellKnown" +>record2 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique2]: "unique2"; readonly [unique1]: "unique1New"; readonly [Symbol.match]: "wellKnown"; } +>wellKnown : unique symbol + +export const record3 = { +>record3 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique1]: "unique1"; readonly [unique2]: "unique2"; readonly [Symbol.match]: "wellKnown"; } +>{ [single]: "single", [twin2]: "twin", [unique1]: "unique1", [unique2]: "unique2", [wellKnown]: "wellKnown",} as const : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique1]: "unique1"; readonly [unique2]: "unique2"; readonly [Symbol.match]: "wellKnown"; } +>{ [single]: "single", [twin2]: "twin", [unique1]: "unique1", [unique2]: "unique2", [wellKnown]: "wellKnown",} : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique1]: "unique1"; readonly [unique2]: "unique2"; readonly [Symbol.match]: "wellKnown"; } + + [single]: "single", +>[single] : "single" +>single : RegisteredSymbol<"single"> +>"single" : "single" + + [twin2]: "twin", +>[twin2] : "twin" +>twin2 : RegisteredSymbol<"twin"> +>"twin" : "twin" + + [unique1]: "unique1", +>[unique1] : "unique1" +>unique1 : unique symbol +>"unique1" : "unique1" + + [unique2]: "unique2", +>[unique2] : "unique2" +>unique2 : unique symbol +>"unique2" : "unique2" + + [wellKnown]: "wellKnown", +>[wellKnown] : "wellKnown" +>wellKnown : unique symbol +>"wellKnown" : "wellKnown" + +} as const; +singleVal = record3[single] satisfies "single"; +>singleVal = record3[single] satisfies "single" : "single" +>singleVal : string +>record3[single] satisfies "single" : "single" +>record3[single] : "single" +>record3 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique1]: "unique1"; readonly [unique2]: "unique2"; readonly [Symbol.match]: "wellKnown"; } +>single : RegisteredSymbol<"single"> + +twin1Val = record3[twin1] satisfies "twin"; +>twin1Val = record3[twin1] satisfies "twin" : "twin" +>twin1Val : string +>record3[twin1] satisfies "twin" : "twin" +>record3[twin1] : "twin" +>record3 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique1]: "unique1"; readonly [unique2]: "unique2"; readonly [Symbol.match]: "wellKnown"; } +>twin1 : RegisteredSymbol<"twin"> + +twin2Val = record3[twin2] satisfies "twin"; +>twin2Val = record3[twin2] satisfies "twin" : "twin" +>twin2Val : string +>record3[twin2] satisfies "twin" : "twin" +>record3[twin2] : "twin" +>record3 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique1]: "unique1"; readonly [unique2]: "unique2"; readonly [Symbol.match]: "wellKnown"; } +>twin2 : RegisteredSymbol<"twin"> + +unique1Val = record3[unique1] satisfies "unique1"; +>unique1Val = record3[unique1] satisfies "unique1" : "unique1" +>unique1Val : string +>record3[unique1] satisfies "unique1" : "unique1" +>record3[unique1] : "unique1" +>record3 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique1]: "unique1"; readonly [unique2]: "unique2"; readonly [Symbol.match]: "wellKnown"; } +>unique1 : unique symbol + +unique2Val = record3[unique2] satisfies "unique2"; +>unique2Val = record3[unique2] satisfies "unique2" : "unique2" +>unique2Val : string +>record3[unique2] satisfies "unique2" : "unique2" +>record3[unique2] : "unique2" +>record3 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique1]: "unique1"; readonly [unique2]: "unique2"; readonly [Symbol.match]: "wellKnown"; } +>unique2 : unique symbol + +wellKnownVal = record3[wellKnown] satisfies "wellKnown"; +>wellKnownVal = record3[wellKnown] satisfies "wellKnown" : "wellKnown" +>wellKnownVal : string +>record3[wellKnown] satisfies "wellKnown" : "wellKnown" +>record3[wellKnown] : "wellKnown" +>record3 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique1]: "unique1"; readonly [unique2]: "unique2"; readonly [Symbol.match]: "wellKnown"; } +>wellKnown : unique symbol + +export const record4 = { +>record4 : { readonly [Symbol.toStringTag]: "wellKnown2"; } +>{ [wellKnown2]: "wellKnown2",} as const : { readonly [Symbol.toStringTag]: "wellKnown2"; } +>{ [wellKnown2]: "wellKnown2",} : { readonly [Symbol.toStringTag]: "wellKnown2"; } + + [wellKnown2]: "wellKnown2", +>[wellKnown2] : "wellKnown2" +>wellKnown2 : unique symbol +>"wellKnown2" : "wellKnown2" + +} as const; +export let wellKnown2Val: string = record4[wellKnown2] satisfies "wellKnown2"; +>wellKnown2Val : string +>record4[wellKnown2] satisfies "wellKnown2" : "wellKnown2" +>record4[wellKnown2] : "wellKnown2" +>record4 : { readonly [Symbol.toStringTag]: "wellKnown2"; } +>wellKnown2 : unique symbol + diff --git a/testdata/tests/cases/compiler/registeredSymbolPropertyAccess.ts b/testdata/tests/cases/compiler/registeredSymbolPropertyAccess.ts new file mode 100644 index 0000000000000..5a9e7cc919c2b --- /dev/null +++ b/testdata/tests/cases/compiler/registeredSymbolPropertyAccess.ts @@ -0,0 +1,54 @@ +// @target: es2015 +// @declaration: true +// @emitDeclarationOnly: true + +export const single = Symbol.for("single"); +export const twin1 = Symbol.for("twin"); +export const twin2 = Symbol.for("twin"); +export const unique1 = Symbol("unique"); +export const unique2 = Symbol("unique"); +export const wellKnown = Symbol.match; +export const wellKnown2 = Symbol.toStringTag; + +export const record1 = { + [single]: "single", + [twin2]: "twin", + [unique1]: "unique1", + [unique2]: "unique2", +} as const; +export let singleVal: string = record1[single] satisfies "single"; +export let twin1Val: string = record1[twin1] satisfies "twin"; +export let twin2Val: string = record1[twin2] satisfies "twin"; +export let unique1Val: string = record1[unique1] satisfies "unique1"; +export let unique2Val: string = record1[unique2] satisfies "unique2"; + +export const record2 = { + ...record1, + [unique1]: "unique1New", + [wellKnown]: "wellKnown", +} as const; +singleVal = record2[single] satisfies "single"; +twin1Val = record2[twin1] satisfies "twin"; +twin2Val = record2[twin2] satisfies "twin"; +unique1Val = record2[unique1] satisfies "unique1New"; +unique2Val = record2[unique2] satisfies "unique2"; +export let wellKnownVal: string = record2[wellKnown] satisfies "wellKnown"; + +export const record3 = { + [single]: "single", + [twin2]: "twin", + [unique1]: "unique1", + [unique2]: "unique2", + [wellKnown]: "wellKnown", +} as const; +singleVal = record3[single] satisfies "single"; +twin1Val = record3[twin1] satisfies "twin"; +twin2Val = record3[twin2] satisfies "twin"; +unique1Val = record3[unique1] satisfies "unique1"; +unique2Val = record3[unique2] satisfies "unique2"; +wellKnownVal = record3[wellKnown] satisfies "wellKnown"; + +export const record4 = { + [wellKnown2]: "wellKnown2", +} as const; +export let wellKnown2Val: string = record4[wellKnown2] satisfies "wellKnown2"; From f42f4221e4242726879ee6abc06647456c5de4f1 Mon Sep 17 00:00:00 2001 From: Michael FIG Date: Fri, 25 Sep 2026 14:11:45 -0600 Subject: [PATCH 4/6] Place symbol compiler tests in active testdata Move the new test cases and accepted baselines into tsc/testdata so the compiler test runner executes them. Regenerate baselines with the repository's CRLF convention. Co-authored-by: Codex --- .../registeredSymbolIntrinsic.symbols | 126 ++-- .../compiler/registeredSymbolIntrinsic.types | 130 ++--- .../registeredSymbolPropertyAccess.js | 90 +-- .../registeredSymbolPropertyAccess.symbols | 412 ++++++------- .../registeredSymbolPropertyAccess.types | 550 +++++++++--------- .../uniqueSymbolConstLikeWidening.symbols | 80 +-- .../uniqueSymbolConstLikeWidening.types | 80 +-- .../compiler/registeredSymbolIntrinsic.ts | 0 .../registeredSymbolPropertyAccess.ts | 0 .../compiler/uniqueSymbolConstLikeWidening.ts | 0 10 files changed, 734 insertions(+), 734 deletions(-) rename {testdata => tsc/testdata}/baselines/reference/compiler/registeredSymbolIntrinsic.symbols (98%) rename {testdata => tsc/testdata}/baselines/reference/compiler/registeredSymbolIntrinsic.types (96%) rename {testdata => tsc/testdata}/baselines/reference/compiler/registeredSymbolPropertyAccess.js (98%) rename {testdata => tsc/testdata}/baselines/reference/compiler/registeredSymbolPropertyAccess.symbols (98%) rename {testdata => tsc/testdata}/baselines/reference/compiler/registeredSymbolPropertyAccess.types (97%) rename {testdata => tsc/testdata}/baselines/reference/compiler/uniqueSymbolConstLikeWidening.symbols (97%) rename {testdata => tsc/testdata}/baselines/reference/compiler/uniqueSymbolConstLikeWidening.types (95%) rename {testdata => tsc/testdata}/tests/cases/compiler/registeredSymbolIntrinsic.ts (100%) rename {testdata => tsc/testdata}/tests/cases/compiler/registeredSymbolPropertyAccess.ts (100%) rename {testdata => tsc/testdata}/tests/cases/compiler/uniqueSymbolConstLikeWidening.ts (100%) diff --git a/testdata/baselines/reference/compiler/registeredSymbolIntrinsic.symbols b/tsc/testdata/baselines/reference/compiler/registeredSymbolIntrinsic.symbols similarity index 98% rename from testdata/baselines/reference/compiler/registeredSymbolIntrinsic.symbols rename to tsc/testdata/baselines/reference/compiler/registeredSymbolIntrinsic.symbols index 41f68d3515f0b..464849c20f266 100644 --- a/testdata/baselines/reference/compiler/registeredSymbolIntrinsic.symbols +++ b/tsc/testdata/baselines/reference/compiler/registeredSymbolIntrinsic.symbols @@ -1,63 +1,63 @@ -//// [tests/cases/compiler/registeredSymbolIntrinsic.ts] //// - -=== registeredSymbolIntrinsic.ts === -const foo = Symbol.for("foo"); ->foo : Symbol(foo, Decl(registeredSymbolIntrinsic.ts, 0, 5)) ->Symbol.for : Symbol(SymbolConstructor.for, Decl(lib.es2015.symbol.d.ts, --, --)) ->Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) ->for : Symbol(SymbolConstructor.for, Decl(lib.es2015.symbol.d.ts, --, --)) - -const fooAgain = Symbol.for("foo"); ->fooAgain : Symbol(fooAgain, Decl(registeredSymbolIntrinsic.ts, 1, 5)) ->Symbol.for : Symbol(SymbolConstructor.for, Decl(lib.es2015.symbol.d.ts, --, --)) ->Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) ->for : Symbol(SymbolConstructor.for, Decl(lib.es2015.symbol.d.ts, --, --)) - -const bar = Symbol.for("bar"); ->bar : Symbol(bar, Decl(registeredSymbolIntrinsic.ts, 2, 5)) ->Symbol.for : Symbol(SymbolConstructor.for, Decl(lib.es2015.symbol.d.ts, --, --)) ->Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) ->for : Symbol(SymbolConstructor.for, Decl(lib.es2015.symbol.d.ts, --, --)) - -let sameStringKey: typeof foo = fooAgain; ->sameStringKey : Symbol(sameStringKey, Decl(registeredSymbolIntrinsic.ts, 4, 3)) ->foo : Symbol(foo, Decl(registeredSymbolIntrinsic.ts, 0, 5)) ->fooAgain : Symbol(fooAgain, Decl(registeredSymbolIntrinsic.ts, 1, 5)) - -let registeredStringKey: RegisteredSymbol<"foo"> = foo; ->registeredStringKey : Symbol(registeredStringKey, Decl(registeredSymbolIntrinsic.ts, 5, 3)) ->RegisteredSymbol : Symbol(RegisteredSymbol, Decl(lib.es2015.symbol.d.ts, --, --)) ->foo : Symbol(foo, Decl(registeredSymbolIntrinsic.ts, 0, 5)) - -let registeredBarKey: RegisteredSymbol<"bar"> = bar; ->registeredBarKey : Symbol(registeredBarKey, Decl(registeredSymbolIntrinsic.ts, 6, 3)) ->RegisteredSymbol : Symbol(RegisteredSymbol, Decl(lib.es2015.symbol.d.ts, --, --)) ->bar : Symbol(bar, Decl(registeredSymbolIntrinsic.ts, 2, 5)) - -let widenedSymbol: symbol = foo; ->widenedSymbol : Symbol(widenedSymbol, Decl(registeredSymbolIntrinsic.ts, 7, 3)) ->foo : Symbol(foo, Decl(registeredSymbolIntrinsic.ts, 0, 5)) - -declare const key: string; ->key : Symbol(key, Decl(registeredSymbolIntrinsic.ts, 9, 13)) - -let registeredString: RegisteredSymbol = Symbol.for(key); ->registeredString : Symbol(registeredString, Decl(registeredSymbolIntrinsic.ts, 10, 3)) ->RegisteredSymbol : Symbol(RegisteredSymbol, Decl(lib.es2015.symbol.d.ts, --, --)) ->Symbol.for : Symbol(SymbolConstructor.for, Decl(lib.es2015.symbol.d.ts, --, --)) ->Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) ->for : Symbol(SymbolConstructor.for, Decl(lib.es2015.symbol.d.ts, --, --)) ->key : Symbol(key, Decl(registeredSymbolIntrinsic.ts, 9, 13)) - -interface WithRegisteredKeys { ->WithRegisteredKeys : Symbol(WithRegisteredKeys, Decl(registeredSymbolIntrinsic.ts, 10, 65)) - - [foo]: string; ->[foo] : Symbol(WithRegisteredKeys[foo], Decl(registeredSymbolIntrinsic.ts, 12, 30)) ->foo : Symbol(foo, Decl(registeredSymbolIntrinsic.ts, 0, 5)) - - [bar]: number; ->[bar] : Symbol(WithRegisteredKeys[bar], Decl(registeredSymbolIntrinsic.ts, 13, 18)) ->bar : Symbol(bar, Decl(registeredSymbolIntrinsic.ts, 2, 5)) -} - +//// [tests/cases/compiler/registeredSymbolIntrinsic.ts] //// + +=== registeredSymbolIntrinsic.ts === +const foo = Symbol.for("foo"); +>foo : Symbol(foo, Decl(registeredSymbolIntrinsic.ts, 0, 5)) +>Symbol.for : Symbol(SymbolConstructor.for, Decl(lib.es2015.symbol.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>for : Symbol(SymbolConstructor.for, Decl(lib.es2015.symbol.d.ts, --, --)) + +const fooAgain = Symbol.for("foo"); +>fooAgain : Symbol(fooAgain, Decl(registeredSymbolIntrinsic.ts, 1, 5)) +>Symbol.for : Symbol(SymbolConstructor.for, Decl(lib.es2015.symbol.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>for : Symbol(SymbolConstructor.for, Decl(lib.es2015.symbol.d.ts, --, --)) + +const bar = Symbol.for("bar"); +>bar : Symbol(bar, Decl(registeredSymbolIntrinsic.ts, 2, 5)) +>Symbol.for : Symbol(SymbolConstructor.for, Decl(lib.es2015.symbol.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>for : Symbol(SymbolConstructor.for, Decl(lib.es2015.symbol.d.ts, --, --)) + +let sameStringKey: typeof foo = fooAgain; +>sameStringKey : Symbol(sameStringKey, Decl(registeredSymbolIntrinsic.ts, 4, 3)) +>foo : Symbol(foo, Decl(registeredSymbolIntrinsic.ts, 0, 5)) +>fooAgain : Symbol(fooAgain, Decl(registeredSymbolIntrinsic.ts, 1, 5)) + +let registeredStringKey: RegisteredSymbol<"foo"> = foo; +>registeredStringKey : Symbol(registeredStringKey, Decl(registeredSymbolIntrinsic.ts, 5, 3)) +>RegisteredSymbol : Symbol(RegisteredSymbol, Decl(lib.es2015.symbol.d.ts, --, --)) +>foo : Symbol(foo, Decl(registeredSymbolIntrinsic.ts, 0, 5)) + +let registeredBarKey: RegisteredSymbol<"bar"> = bar; +>registeredBarKey : Symbol(registeredBarKey, Decl(registeredSymbolIntrinsic.ts, 6, 3)) +>RegisteredSymbol : Symbol(RegisteredSymbol, Decl(lib.es2015.symbol.d.ts, --, --)) +>bar : Symbol(bar, Decl(registeredSymbolIntrinsic.ts, 2, 5)) + +let widenedSymbol: symbol = foo; +>widenedSymbol : Symbol(widenedSymbol, Decl(registeredSymbolIntrinsic.ts, 7, 3)) +>foo : Symbol(foo, Decl(registeredSymbolIntrinsic.ts, 0, 5)) + +declare const key: string; +>key : Symbol(key, Decl(registeredSymbolIntrinsic.ts, 9, 13)) + +let registeredString: RegisteredSymbol = Symbol.for(key); +>registeredString : Symbol(registeredString, Decl(registeredSymbolIntrinsic.ts, 10, 3)) +>RegisteredSymbol : Symbol(RegisteredSymbol, Decl(lib.es2015.symbol.d.ts, --, --)) +>Symbol.for : Symbol(SymbolConstructor.for, Decl(lib.es2015.symbol.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>for : Symbol(SymbolConstructor.for, Decl(lib.es2015.symbol.d.ts, --, --)) +>key : Symbol(key, Decl(registeredSymbolIntrinsic.ts, 9, 13)) + +interface WithRegisteredKeys { +>WithRegisteredKeys : Symbol(WithRegisteredKeys, Decl(registeredSymbolIntrinsic.ts, 10, 65)) + + [foo]: string; +>[foo] : Symbol(WithRegisteredKeys[foo], Decl(registeredSymbolIntrinsic.ts, 12, 30)) +>foo : Symbol(foo, Decl(registeredSymbolIntrinsic.ts, 0, 5)) + + [bar]: number; +>[bar] : Symbol(WithRegisteredKeys[bar], Decl(registeredSymbolIntrinsic.ts, 13, 18)) +>bar : Symbol(bar, Decl(registeredSymbolIntrinsic.ts, 2, 5)) +} + diff --git a/testdata/baselines/reference/compiler/registeredSymbolIntrinsic.types b/tsc/testdata/baselines/reference/compiler/registeredSymbolIntrinsic.types similarity index 96% rename from testdata/baselines/reference/compiler/registeredSymbolIntrinsic.types rename to tsc/testdata/baselines/reference/compiler/registeredSymbolIntrinsic.types index d12d6444c725a..8129e7620ae39 100644 --- a/testdata/baselines/reference/compiler/registeredSymbolIntrinsic.types +++ b/tsc/testdata/baselines/reference/compiler/registeredSymbolIntrinsic.types @@ -1,65 +1,65 @@ -//// [tests/cases/compiler/registeredSymbolIntrinsic.ts] //// - -=== registeredSymbolIntrinsic.ts === -const foo = Symbol.for("foo"); ->foo : RegisteredSymbol<"foo"> ->Symbol.for("foo") : RegisteredSymbol<"foo"> ->Symbol.for : (key: Key) => RegisteredSymbol ->Symbol : SymbolConstructor ->for : (key: Key) => RegisteredSymbol ->"foo" : "foo" - -const fooAgain = Symbol.for("foo"); ->fooAgain : RegisteredSymbol<"foo"> ->Symbol.for("foo") : RegisteredSymbol<"foo"> ->Symbol.for : (key: Key) => RegisteredSymbol ->Symbol : SymbolConstructor ->for : (key: Key) => RegisteredSymbol ->"foo" : "foo" - -const bar = Symbol.for("bar"); ->bar : RegisteredSymbol<"bar"> ->Symbol.for("bar") : RegisteredSymbol<"bar"> ->Symbol.for : (key: Key) => RegisteredSymbol ->Symbol : SymbolConstructor ->for : (key: Key) => RegisteredSymbol ->"bar" : "bar" - -let sameStringKey: typeof foo = fooAgain; ->sameStringKey : RegisteredSymbol<"foo"> ->foo : RegisteredSymbol<"foo"> ->fooAgain : RegisteredSymbol<"foo"> - -let registeredStringKey: RegisteredSymbol<"foo"> = foo; ->registeredStringKey : RegisteredSymbol<"foo"> ->foo : RegisteredSymbol<"foo"> - -let registeredBarKey: RegisteredSymbol<"bar"> = bar; ->registeredBarKey : RegisteredSymbol<"bar"> ->bar : RegisteredSymbol<"bar"> - -let widenedSymbol: symbol = foo; ->widenedSymbol : symbol ->foo : RegisteredSymbol<"foo"> - -declare const key: string; ->key : string - -let registeredString: RegisteredSymbol = Symbol.for(key); ->registeredString : RegisteredSymbol ->Symbol.for(key) : RegisteredSymbol ->Symbol.for : (key: Key) => RegisteredSymbol ->Symbol : SymbolConstructor ->for : (key: Key) => RegisteredSymbol ->key : string - -interface WithRegisteredKeys { - [foo]: string; ->[foo] : string ->foo : RegisteredSymbol<"foo"> - - [bar]: number; ->[bar] : number ->bar : RegisteredSymbol<"bar"> -} - +//// [tests/cases/compiler/registeredSymbolIntrinsic.ts] //// + +=== registeredSymbolIntrinsic.ts === +const foo = Symbol.for("foo"); +>foo : RegisteredSymbol<"foo"> +>Symbol.for("foo") : RegisteredSymbol<"foo"> +>Symbol.for : (key: Key) => RegisteredSymbol +>Symbol : SymbolConstructor +>for : (key: Key) => RegisteredSymbol +>"foo" : "foo" + +const fooAgain = Symbol.for("foo"); +>fooAgain : RegisteredSymbol<"foo"> +>Symbol.for("foo") : RegisteredSymbol<"foo"> +>Symbol.for : (key: Key) => RegisteredSymbol +>Symbol : SymbolConstructor +>for : (key: Key) => RegisteredSymbol +>"foo" : "foo" + +const bar = Symbol.for("bar"); +>bar : RegisteredSymbol<"bar"> +>Symbol.for("bar") : RegisteredSymbol<"bar"> +>Symbol.for : (key: Key) => RegisteredSymbol +>Symbol : SymbolConstructor +>for : (key: Key) => RegisteredSymbol +>"bar" : "bar" + +let sameStringKey: typeof foo = fooAgain; +>sameStringKey : RegisteredSymbol<"foo"> +>foo : RegisteredSymbol<"foo"> +>fooAgain : RegisteredSymbol<"foo"> + +let registeredStringKey: RegisteredSymbol<"foo"> = foo; +>registeredStringKey : RegisteredSymbol<"foo"> +>foo : RegisteredSymbol<"foo"> + +let registeredBarKey: RegisteredSymbol<"bar"> = bar; +>registeredBarKey : RegisteredSymbol<"bar"> +>bar : RegisteredSymbol<"bar"> + +let widenedSymbol: symbol = foo; +>widenedSymbol : symbol +>foo : RegisteredSymbol<"foo"> + +declare const key: string; +>key : string + +let registeredString: RegisteredSymbol = Symbol.for(key); +>registeredString : RegisteredSymbol +>Symbol.for(key) : RegisteredSymbol +>Symbol.for : (key: Key) => RegisteredSymbol +>Symbol : SymbolConstructor +>for : (key: Key) => RegisteredSymbol +>key : string + +interface WithRegisteredKeys { + [foo]: string; +>[foo] : string +>foo : RegisteredSymbol<"foo"> + + [bar]: number; +>[bar] : number +>bar : RegisteredSymbol<"bar"> +} + diff --git a/testdata/baselines/reference/compiler/registeredSymbolPropertyAccess.js b/tsc/testdata/baselines/reference/compiler/registeredSymbolPropertyAccess.js similarity index 98% rename from testdata/baselines/reference/compiler/registeredSymbolPropertyAccess.js rename to tsc/testdata/baselines/reference/compiler/registeredSymbolPropertyAccess.js index 857c76270a09f..3820c660f7a44 100644 --- a/testdata/baselines/reference/compiler/registeredSymbolPropertyAccess.js +++ b/tsc/testdata/baselines/reference/compiler/registeredSymbolPropertyAccess.js @@ -1,6 +1,6 @@ -//// [tests/cases/compiler/registeredSymbolPropertyAccess.ts] //// - -//// [registeredSymbolPropertyAccess.ts] +//// [tests/cases/compiler/registeredSymbolPropertyAccess.ts] //// + +//// [registeredSymbolPropertyAccess.ts] export const single = Symbol.for("single"); export const twin1 = Symbol.for("twin"); export const twin2 = Symbol.for("twin"); @@ -51,45 +51,45 @@ export const record4 = { [wellKnown2]: "wellKnown2", } as const; export let wellKnown2Val: string = record4[wellKnown2] satisfies "wellKnown2"; - - - - -//// [registeredSymbolPropertyAccess.d.ts] -export declare const single: RegisteredSymbol<"single">; -export declare const twin1: RegisteredSymbol<"twin">; -export declare const twin2: RegisteredSymbol<"twin">; -export declare const unique1: unique symbol; -export declare const unique2: unique symbol; -export declare const wellKnown: typeof Symbol.match; -export declare const wellKnown2: typeof Symbol.toStringTag; -export declare const record1: { - readonly [single]: "single"; - readonly [twin2]: "twin"; - readonly [unique1]: "unique1"; - readonly [unique2]: "unique2"; -}; -export declare let singleVal: string; -export declare let twin1Val: string; -export declare let twin2Val: string; -export declare let unique1Val: string; -export declare let unique2Val: string; -export declare const record2: { - readonly [single]: "single"; - readonly [twin2]: "twin"; - readonly [unique2]: "unique2"; - readonly [unique1]: "unique1New"; - readonly [Symbol.match]: "wellKnown"; -}; -export declare let wellKnownVal: string; -export declare const record3: { - readonly [single]: "single"; - readonly [twin2]: "twin"; - readonly [unique1]: "unique1"; - readonly [unique2]: "unique2"; - readonly [Symbol.match]: "wellKnown"; -}; -export declare const record4: { - readonly [Symbol.toStringTag]: "wellKnown2"; -}; -export declare let wellKnown2Val: string; + + + + +//// [registeredSymbolPropertyAccess.d.ts] +export declare const single: RegisteredSymbol<"single">; +export declare const twin1: RegisteredSymbol<"twin">; +export declare const twin2: RegisteredSymbol<"twin">; +export declare const unique1: unique symbol; +export declare const unique2: unique symbol; +export declare const wellKnown: typeof Symbol.match; +export declare const wellKnown2: typeof Symbol.toStringTag; +export declare const record1: { + readonly [single]: "single"; + readonly [twin2]: "twin"; + readonly [unique1]: "unique1"; + readonly [unique2]: "unique2"; +}; +export declare let singleVal: string; +export declare let twin1Val: string; +export declare let twin2Val: string; +export declare let unique1Val: string; +export declare let unique2Val: string; +export declare const record2: { + readonly [single]: "single"; + readonly [twin2]: "twin"; + readonly [unique2]: "unique2"; + readonly [unique1]: "unique1New"; + readonly [Symbol.match]: "wellKnown"; +}; +export declare let wellKnownVal: string; +export declare const record3: { + readonly [single]: "single"; + readonly [twin2]: "twin"; + readonly [unique1]: "unique1"; + readonly [unique2]: "unique2"; + readonly [Symbol.match]: "wellKnown"; +}; +export declare const record4: { + readonly [Symbol.toStringTag]: "wellKnown2"; +}; +export declare let wellKnown2Val: string; diff --git a/testdata/baselines/reference/compiler/registeredSymbolPropertyAccess.symbols b/tsc/testdata/baselines/reference/compiler/registeredSymbolPropertyAccess.symbols similarity index 98% rename from testdata/baselines/reference/compiler/registeredSymbolPropertyAccess.symbols rename to tsc/testdata/baselines/reference/compiler/registeredSymbolPropertyAccess.symbols index e35b0562a5d73..6fdc07d3e00bd 100644 --- a/testdata/baselines/reference/compiler/registeredSymbolPropertyAccess.symbols +++ b/tsc/testdata/baselines/reference/compiler/registeredSymbolPropertyAccess.symbols @@ -1,206 +1,206 @@ -//// [tests/cases/compiler/registeredSymbolPropertyAccess.ts] //// - -=== registeredSymbolPropertyAccess.ts === -export const single = Symbol.for("single"); ->single : Symbol(single, Decl(registeredSymbolPropertyAccess.ts, 0, 12)) ->Symbol.for : Symbol(SymbolConstructor.for, Decl(lib.es2015.symbol.d.ts, --, --)) ->Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) ->for : Symbol(SymbolConstructor.for, Decl(lib.es2015.symbol.d.ts, --, --)) - -export const twin1 = Symbol.for("twin"); ->twin1 : Symbol(twin1, Decl(registeredSymbolPropertyAccess.ts, 1, 12)) ->Symbol.for : Symbol(SymbolConstructor.for, Decl(lib.es2015.symbol.d.ts, --, --)) ->Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) ->for : Symbol(SymbolConstructor.for, Decl(lib.es2015.symbol.d.ts, --, --)) - -export const twin2 = Symbol.for("twin"); ->twin2 : Symbol(twin2, Decl(registeredSymbolPropertyAccess.ts, 2, 12)) ->Symbol.for : Symbol(SymbolConstructor.for, Decl(lib.es2015.symbol.d.ts, --, --)) ->Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) ->for : Symbol(SymbolConstructor.for, Decl(lib.es2015.symbol.d.ts, --, --)) - -export const unique1 = Symbol("unique"); ->unique1 : Symbol(unique1, Decl(registeredSymbolPropertyAccess.ts, 3, 12)) ->Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) - -export const unique2 = Symbol("unique"); ->unique2 : Symbol(unique2, Decl(registeredSymbolPropertyAccess.ts, 4, 12)) ->Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) - -export const wellKnown = Symbol.match; ->wellKnown : Symbol(wellKnown, Decl(registeredSymbolPropertyAccess.ts, 5, 12)) ->Symbol.match : Symbol(SymbolConstructor.match, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) ->Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) ->match : Symbol(SymbolConstructor.match, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) - -export const wellKnown2 = Symbol.toStringTag; ->wellKnown2 : Symbol(wellKnown2, Decl(registeredSymbolPropertyAccess.ts, 6, 12)) ->Symbol.toStringTag : Symbol(SymbolConstructor.toStringTag, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) ->Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) ->toStringTag : Symbol(SymbolConstructor.toStringTag, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) - -export const record1 = { ->record1 : Symbol(record1, Decl(registeredSymbolPropertyAccess.ts, 8, 12)) - - [single]: "single", ->[single] : Symbol([single], Decl(registeredSymbolPropertyAccess.ts, 8, 24)) ->single : Symbol(single, Decl(registeredSymbolPropertyAccess.ts, 0, 12)) - - [twin2]: "twin", ->[twin2] : Symbol([twin2], Decl(registeredSymbolPropertyAccess.ts, 9, 23)) ->twin2 : Symbol(twin2, Decl(registeredSymbolPropertyAccess.ts, 2, 12)) - - [unique1]: "unique1", ->[unique1] : Symbol([unique1], Decl(registeredSymbolPropertyAccess.ts, 10, 20)) ->unique1 : Symbol(unique1, Decl(registeredSymbolPropertyAccess.ts, 3, 12)) - - [unique2]: "unique2", ->[unique2] : Symbol([unique2], Decl(registeredSymbolPropertyAccess.ts, 11, 25)) ->unique2 : Symbol(unique2, Decl(registeredSymbolPropertyAccess.ts, 4, 12)) - -} as const; ->const : Symbol(const) - -export let singleVal: string = record1[single] satisfies "single"; ->singleVal : Symbol(singleVal, Decl(registeredSymbolPropertyAccess.ts, 14, 10)) ->record1 : Symbol(record1, Decl(registeredSymbolPropertyAccess.ts, 8, 12)) ->single : Symbol(single, Decl(registeredSymbolPropertyAccess.ts, 0, 12)) - -export let twin1Val: string = record1[twin1] satisfies "twin"; ->twin1Val : Symbol(twin1Val, Decl(registeredSymbolPropertyAccess.ts, 15, 10)) ->record1 : Symbol(record1, Decl(registeredSymbolPropertyAccess.ts, 8, 12)) ->twin1 : Symbol(twin1, Decl(registeredSymbolPropertyAccess.ts, 1, 12)) - -export let twin2Val: string = record1[twin2] satisfies "twin"; ->twin2Val : Symbol(twin2Val, Decl(registeredSymbolPropertyAccess.ts, 16, 10)) ->record1 : Symbol(record1, Decl(registeredSymbolPropertyAccess.ts, 8, 12)) ->twin2 : Symbol(twin2, Decl(registeredSymbolPropertyAccess.ts, 2, 12)) - -export let unique1Val: string = record1[unique1] satisfies "unique1"; ->unique1Val : Symbol(unique1Val, Decl(registeredSymbolPropertyAccess.ts, 17, 10)) ->record1 : Symbol(record1, Decl(registeredSymbolPropertyAccess.ts, 8, 12)) ->unique1 : Symbol(unique1, Decl(registeredSymbolPropertyAccess.ts, 3, 12)) - -export let unique2Val: string = record1[unique2] satisfies "unique2"; ->unique2Val : Symbol(unique2Val, Decl(registeredSymbolPropertyAccess.ts, 18, 10)) ->record1 : Symbol(record1, Decl(registeredSymbolPropertyAccess.ts, 8, 12)) ->unique2 : Symbol(unique2, Decl(registeredSymbolPropertyAccess.ts, 4, 12)) - -export const record2 = { ->record2 : Symbol(record2, Decl(registeredSymbolPropertyAccess.ts, 20, 12)) - - ...record1, ->record1 : Symbol(record1, Decl(registeredSymbolPropertyAccess.ts, 8, 12)) - - [unique1]: "unique1New", ->[unique1] : Symbol([unique1], Decl(registeredSymbolPropertyAccess.ts, 21, 15)) ->unique1 : Symbol(unique1, Decl(registeredSymbolPropertyAccess.ts, 3, 12)) - - [wellKnown]: "wellKnown", ->[wellKnown] : Symbol([wellKnown], Decl(registeredSymbolPropertyAccess.ts, 22, 28)) ->wellKnown : Symbol(wellKnown, Decl(registeredSymbolPropertyAccess.ts, 5, 12)) - -} as const; ->const : Symbol(const) - -singleVal = record2[single] satisfies "single"; ->singleVal : Symbol(singleVal, Decl(registeredSymbolPropertyAccess.ts, 14, 10)) ->record2 : Symbol(record2, Decl(registeredSymbolPropertyAccess.ts, 20, 12)) ->single : Symbol(single, Decl(registeredSymbolPropertyAccess.ts, 0, 12)) - -twin1Val = record2[twin1] satisfies "twin"; ->twin1Val : Symbol(twin1Val, Decl(registeredSymbolPropertyAccess.ts, 15, 10)) ->record2 : Symbol(record2, Decl(registeredSymbolPropertyAccess.ts, 20, 12)) ->twin1 : Symbol(twin1, Decl(registeredSymbolPropertyAccess.ts, 1, 12)) - -twin2Val = record2[twin2] satisfies "twin"; ->twin2Val : Symbol(twin2Val, Decl(registeredSymbolPropertyAccess.ts, 16, 10)) ->record2 : Symbol(record2, Decl(registeredSymbolPropertyAccess.ts, 20, 12)) ->twin2 : Symbol(twin2, Decl(registeredSymbolPropertyAccess.ts, 2, 12)) - -unique1Val = record2[unique1] satisfies "unique1New"; ->unique1Val : Symbol(unique1Val, Decl(registeredSymbolPropertyAccess.ts, 17, 10)) ->record2 : Symbol(record2, Decl(registeredSymbolPropertyAccess.ts, 20, 12)) ->unique1 : Symbol(unique1, Decl(registeredSymbolPropertyAccess.ts, 3, 12)) - -unique2Val = record2[unique2] satisfies "unique2"; ->unique2Val : Symbol(unique2Val, Decl(registeredSymbolPropertyAccess.ts, 18, 10)) ->record2 : Symbol(record2, Decl(registeredSymbolPropertyAccess.ts, 20, 12)) ->unique2 : Symbol(unique2, Decl(registeredSymbolPropertyAccess.ts, 4, 12)) - -export let wellKnownVal: string = record2[wellKnown] satisfies "wellKnown"; ->wellKnownVal : Symbol(wellKnownVal, Decl(registeredSymbolPropertyAccess.ts, 30, 10)) ->record2 : Symbol(record2, Decl(registeredSymbolPropertyAccess.ts, 20, 12)) ->wellKnown : Symbol(wellKnown, Decl(registeredSymbolPropertyAccess.ts, 5, 12)) - -export const record3 = { ->record3 : Symbol(record3, Decl(registeredSymbolPropertyAccess.ts, 32, 12)) - - [single]: "single", ->[single] : Symbol([single], Decl(registeredSymbolPropertyAccess.ts, 32, 24)) ->single : Symbol(single, Decl(registeredSymbolPropertyAccess.ts, 0, 12)) - - [twin2]: "twin", ->[twin2] : Symbol([twin2], Decl(registeredSymbolPropertyAccess.ts, 33, 23)) ->twin2 : Symbol(twin2, Decl(registeredSymbolPropertyAccess.ts, 2, 12)) - - [unique1]: "unique1", ->[unique1] : Symbol([unique1], Decl(registeredSymbolPropertyAccess.ts, 34, 20)) ->unique1 : Symbol(unique1, Decl(registeredSymbolPropertyAccess.ts, 3, 12)) - - [unique2]: "unique2", ->[unique2] : Symbol([unique2], Decl(registeredSymbolPropertyAccess.ts, 35, 25)) ->unique2 : Symbol(unique2, Decl(registeredSymbolPropertyAccess.ts, 4, 12)) - - [wellKnown]: "wellKnown", ->[wellKnown] : Symbol([wellKnown], Decl(registeredSymbolPropertyAccess.ts, 36, 25)) ->wellKnown : Symbol(wellKnown, Decl(registeredSymbolPropertyAccess.ts, 5, 12)) - -} as const; ->const : Symbol(const) - -singleVal = record3[single] satisfies "single"; ->singleVal : Symbol(singleVal, Decl(registeredSymbolPropertyAccess.ts, 14, 10)) ->record3 : Symbol(record3, Decl(registeredSymbolPropertyAccess.ts, 32, 12)) ->single : Symbol(single, Decl(registeredSymbolPropertyAccess.ts, 0, 12)) - -twin1Val = record3[twin1] satisfies "twin"; ->twin1Val : Symbol(twin1Val, Decl(registeredSymbolPropertyAccess.ts, 15, 10)) ->record3 : Symbol(record3, Decl(registeredSymbolPropertyAccess.ts, 32, 12)) ->twin1 : Symbol(twin1, Decl(registeredSymbolPropertyAccess.ts, 1, 12)) - -twin2Val = record3[twin2] satisfies "twin"; ->twin2Val : Symbol(twin2Val, Decl(registeredSymbolPropertyAccess.ts, 16, 10)) ->record3 : Symbol(record3, Decl(registeredSymbolPropertyAccess.ts, 32, 12)) ->twin2 : Symbol(twin2, Decl(registeredSymbolPropertyAccess.ts, 2, 12)) - -unique1Val = record3[unique1] satisfies "unique1"; ->unique1Val : Symbol(unique1Val, Decl(registeredSymbolPropertyAccess.ts, 17, 10)) ->record3 : Symbol(record3, Decl(registeredSymbolPropertyAccess.ts, 32, 12)) ->unique1 : Symbol(unique1, Decl(registeredSymbolPropertyAccess.ts, 3, 12)) - -unique2Val = record3[unique2] satisfies "unique2"; ->unique2Val : Symbol(unique2Val, Decl(registeredSymbolPropertyAccess.ts, 18, 10)) ->record3 : Symbol(record3, Decl(registeredSymbolPropertyAccess.ts, 32, 12)) ->unique2 : Symbol(unique2, Decl(registeredSymbolPropertyAccess.ts, 4, 12)) - -wellKnownVal = record3[wellKnown] satisfies "wellKnown"; ->wellKnownVal : Symbol(wellKnownVal, Decl(registeredSymbolPropertyAccess.ts, 30, 10)) ->record3 : Symbol(record3, Decl(registeredSymbolPropertyAccess.ts, 32, 12)) ->wellKnown : Symbol(wellKnown, Decl(registeredSymbolPropertyAccess.ts, 5, 12)) - -export const record4 = { ->record4 : Symbol(record4, Decl(registeredSymbolPropertyAccess.ts, 46, 12)) - - [wellKnown2]: "wellKnown2", ->[wellKnown2] : Symbol([wellKnown2], Decl(registeredSymbolPropertyAccess.ts, 46, 24)) ->wellKnown2 : Symbol(wellKnown2, Decl(registeredSymbolPropertyAccess.ts, 6, 12)) - -} as const; ->const : Symbol(const) - -export let wellKnown2Val: string = record4[wellKnown2] satisfies "wellKnown2"; ->wellKnown2Val : Symbol(wellKnown2Val, Decl(registeredSymbolPropertyAccess.ts, 49, 10)) ->record4 : Symbol(record4, Decl(registeredSymbolPropertyAccess.ts, 46, 12)) ->wellKnown2 : Symbol(wellKnown2, Decl(registeredSymbolPropertyAccess.ts, 6, 12)) - +//// [tests/cases/compiler/registeredSymbolPropertyAccess.ts] //// + +=== registeredSymbolPropertyAccess.ts === +export const single = Symbol.for("single"); +>single : Symbol(single, Decl(registeredSymbolPropertyAccess.ts, 0, 12)) +>Symbol.for : Symbol(SymbolConstructor.for, Decl(lib.es2015.symbol.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>for : Symbol(SymbolConstructor.for, Decl(lib.es2015.symbol.d.ts, --, --)) + +export const twin1 = Symbol.for("twin"); +>twin1 : Symbol(twin1, Decl(registeredSymbolPropertyAccess.ts, 1, 12)) +>Symbol.for : Symbol(SymbolConstructor.for, Decl(lib.es2015.symbol.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>for : Symbol(SymbolConstructor.for, Decl(lib.es2015.symbol.d.ts, --, --)) + +export const twin2 = Symbol.for("twin"); +>twin2 : Symbol(twin2, Decl(registeredSymbolPropertyAccess.ts, 2, 12)) +>Symbol.for : Symbol(SymbolConstructor.for, Decl(lib.es2015.symbol.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>for : Symbol(SymbolConstructor.for, Decl(lib.es2015.symbol.d.ts, --, --)) + +export const unique1 = Symbol("unique"); +>unique1 : Symbol(unique1, Decl(registeredSymbolPropertyAccess.ts, 3, 12)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + +export const unique2 = Symbol("unique"); +>unique2 : Symbol(unique2, Decl(registeredSymbolPropertyAccess.ts, 4, 12)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + +export const wellKnown = Symbol.match; +>wellKnown : Symbol(wellKnown, Decl(registeredSymbolPropertyAccess.ts, 5, 12)) +>Symbol.match : Symbol(SymbolConstructor.match, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>match : Symbol(SymbolConstructor.match, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + +export const wellKnown2 = Symbol.toStringTag; +>wellKnown2 : Symbol(wellKnown2, Decl(registeredSymbolPropertyAccess.ts, 6, 12)) +>Symbol.toStringTag : Symbol(SymbolConstructor.toStringTag, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>toStringTag : Symbol(SymbolConstructor.toStringTag, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + +export const record1 = { +>record1 : Symbol(record1, Decl(registeredSymbolPropertyAccess.ts, 8, 12)) + + [single]: "single", +>[single] : Symbol([single], Decl(registeredSymbolPropertyAccess.ts, 8, 24)) +>single : Symbol(single, Decl(registeredSymbolPropertyAccess.ts, 0, 12)) + + [twin2]: "twin", +>[twin2] : Symbol([twin2], Decl(registeredSymbolPropertyAccess.ts, 9, 23)) +>twin2 : Symbol(twin2, Decl(registeredSymbolPropertyAccess.ts, 2, 12)) + + [unique1]: "unique1", +>[unique1] : Symbol([unique1], Decl(registeredSymbolPropertyAccess.ts, 10, 20)) +>unique1 : Symbol(unique1, Decl(registeredSymbolPropertyAccess.ts, 3, 12)) + + [unique2]: "unique2", +>[unique2] : Symbol([unique2], Decl(registeredSymbolPropertyAccess.ts, 11, 25)) +>unique2 : Symbol(unique2, Decl(registeredSymbolPropertyAccess.ts, 4, 12)) + +} as const; +>const : Symbol(const) + +export let singleVal: string = record1[single] satisfies "single"; +>singleVal : Symbol(singleVal, Decl(registeredSymbolPropertyAccess.ts, 14, 10)) +>record1 : Symbol(record1, Decl(registeredSymbolPropertyAccess.ts, 8, 12)) +>single : Symbol(single, Decl(registeredSymbolPropertyAccess.ts, 0, 12)) + +export let twin1Val: string = record1[twin1] satisfies "twin"; +>twin1Val : Symbol(twin1Val, Decl(registeredSymbolPropertyAccess.ts, 15, 10)) +>record1 : Symbol(record1, Decl(registeredSymbolPropertyAccess.ts, 8, 12)) +>twin1 : Symbol(twin1, Decl(registeredSymbolPropertyAccess.ts, 1, 12)) + +export let twin2Val: string = record1[twin2] satisfies "twin"; +>twin2Val : Symbol(twin2Val, Decl(registeredSymbolPropertyAccess.ts, 16, 10)) +>record1 : Symbol(record1, Decl(registeredSymbolPropertyAccess.ts, 8, 12)) +>twin2 : Symbol(twin2, Decl(registeredSymbolPropertyAccess.ts, 2, 12)) + +export let unique1Val: string = record1[unique1] satisfies "unique1"; +>unique1Val : Symbol(unique1Val, Decl(registeredSymbolPropertyAccess.ts, 17, 10)) +>record1 : Symbol(record1, Decl(registeredSymbolPropertyAccess.ts, 8, 12)) +>unique1 : Symbol(unique1, Decl(registeredSymbolPropertyAccess.ts, 3, 12)) + +export let unique2Val: string = record1[unique2] satisfies "unique2"; +>unique2Val : Symbol(unique2Val, Decl(registeredSymbolPropertyAccess.ts, 18, 10)) +>record1 : Symbol(record1, Decl(registeredSymbolPropertyAccess.ts, 8, 12)) +>unique2 : Symbol(unique2, Decl(registeredSymbolPropertyAccess.ts, 4, 12)) + +export const record2 = { +>record2 : Symbol(record2, Decl(registeredSymbolPropertyAccess.ts, 20, 12)) + + ...record1, +>record1 : Symbol(record1, Decl(registeredSymbolPropertyAccess.ts, 8, 12)) + + [unique1]: "unique1New", +>[unique1] : Symbol([unique1], Decl(registeredSymbolPropertyAccess.ts, 21, 15)) +>unique1 : Symbol(unique1, Decl(registeredSymbolPropertyAccess.ts, 3, 12)) + + [wellKnown]: "wellKnown", +>[wellKnown] : Symbol([wellKnown], Decl(registeredSymbolPropertyAccess.ts, 22, 28)) +>wellKnown : Symbol(wellKnown, Decl(registeredSymbolPropertyAccess.ts, 5, 12)) + +} as const; +>const : Symbol(const) + +singleVal = record2[single] satisfies "single"; +>singleVal : Symbol(singleVal, Decl(registeredSymbolPropertyAccess.ts, 14, 10)) +>record2 : Symbol(record2, Decl(registeredSymbolPropertyAccess.ts, 20, 12)) +>single : Symbol(single, Decl(registeredSymbolPropertyAccess.ts, 0, 12)) + +twin1Val = record2[twin1] satisfies "twin"; +>twin1Val : Symbol(twin1Val, Decl(registeredSymbolPropertyAccess.ts, 15, 10)) +>record2 : Symbol(record2, Decl(registeredSymbolPropertyAccess.ts, 20, 12)) +>twin1 : Symbol(twin1, Decl(registeredSymbolPropertyAccess.ts, 1, 12)) + +twin2Val = record2[twin2] satisfies "twin"; +>twin2Val : Symbol(twin2Val, Decl(registeredSymbolPropertyAccess.ts, 16, 10)) +>record2 : Symbol(record2, Decl(registeredSymbolPropertyAccess.ts, 20, 12)) +>twin2 : Symbol(twin2, Decl(registeredSymbolPropertyAccess.ts, 2, 12)) + +unique1Val = record2[unique1] satisfies "unique1New"; +>unique1Val : Symbol(unique1Val, Decl(registeredSymbolPropertyAccess.ts, 17, 10)) +>record2 : Symbol(record2, Decl(registeredSymbolPropertyAccess.ts, 20, 12)) +>unique1 : Symbol(unique1, Decl(registeredSymbolPropertyAccess.ts, 3, 12)) + +unique2Val = record2[unique2] satisfies "unique2"; +>unique2Val : Symbol(unique2Val, Decl(registeredSymbolPropertyAccess.ts, 18, 10)) +>record2 : Symbol(record2, Decl(registeredSymbolPropertyAccess.ts, 20, 12)) +>unique2 : Symbol(unique2, Decl(registeredSymbolPropertyAccess.ts, 4, 12)) + +export let wellKnownVal: string = record2[wellKnown] satisfies "wellKnown"; +>wellKnownVal : Symbol(wellKnownVal, Decl(registeredSymbolPropertyAccess.ts, 30, 10)) +>record2 : Symbol(record2, Decl(registeredSymbolPropertyAccess.ts, 20, 12)) +>wellKnown : Symbol(wellKnown, Decl(registeredSymbolPropertyAccess.ts, 5, 12)) + +export const record3 = { +>record3 : Symbol(record3, Decl(registeredSymbolPropertyAccess.ts, 32, 12)) + + [single]: "single", +>[single] : Symbol([single], Decl(registeredSymbolPropertyAccess.ts, 32, 24)) +>single : Symbol(single, Decl(registeredSymbolPropertyAccess.ts, 0, 12)) + + [twin2]: "twin", +>[twin2] : Symbol([twin2], Decl(registeredSymbolPropertyAccess.ts, 33, 23)) +>twin2 : Symbol(twin2, Decl(registeredSymbolPropertyAccess.ts, 2, 12)) + + [unique1]: "unique1", +>[unique1] : Symbol([unique1], Decl(registeredSymbolPropertyAccess.ts, 34, 20)) +>unique1 : Symbol(unique1, Decl(registeredSymbolPropertyAccess.ts, 3, 12)) + + [unique2]: "unique2", +>[unique2] : Symbol([unique2], Decl(registeredSymbolPropertyAccess.ts, 35, 25)) +>unique2 : Symbol(unique2, Decl(registeredSymbolPropertyAccess.ts, 4, 12)) + + [wellKnown]: "wellKnown", +>[wellKnown] : Symbol([wellKnown], Decl(registeredSymbolPropertyAccess.ts, 36, 25)) +>wellKnown : Symbol(wellKnown, Decl(registeredSymbolPropertyAccess.ts, 5, 12)) + +} as const; +>const : Symbol(const) + +singleVal = record3[single] satisfies "single"; +>singleVal : Symbol(singleVal, Decl(registeredSymbolPropertyAccess.ts, 14, 10)) +>record3 : Symbol(record3, Decl(registeredSymbolPropertyAccess.ts, 32, 12)) +>single : Symbol(single, Decl(registeredSymbolPropertyAccess.ts, 0, 12)) + +twin1Val = record3[twin1] satisfies "twin"; +>twin1Val : Symbol(twin1Val, Decl(registeredSymbolPropertyAccess.ts, 15, 10)) +>record3 : Symbol(record3, Decl(registeredSymbolPropertyAccess.ts, 32, 12)) +>twin1 : Symbol(twin1, Decl(registeredSymbolPropertyAccess.ts, 1, 12)) + +twin2Val = record3[twin2] satisfies "twin"; +>twin2Val : Symbol(twin2Val, Decl(registeredSymbolPropertyAccess.ts, 16, 10)) +>record3 : Symbol(record3, Decl(registeredSymbolPropertyAccess.ts, 32, 12)) +>twin2 : Symbol(twin2, Decl(registeredSymbolPropertyAccess.ts, 2, 12)) + +unique1Val = record3[unique1] satisfies "unique1"; +>unique1Val : Symbol(unique1Val, Decl(registeredSymbolPropertyAccess.ts, 17, 10)) +>record3 : Symbol(record3, Decl(registeredSymbolPropertyAccess.ts, 32, 12)) +>unique1 : Symbol(unique1, Decl(registeredSymbolPropertyAccess.ts, 3, 12)) + +unique2Val = record3[unique2] satisfies "unique2"; +>unique2Val : Symbol(unique2Val, Decl(registeredSymbolPropertyAccess.ts, 18, 10)) +>record3 : Symbol(record3, Decl(registeredSymbolPropertyAccess.ts, 32, 12)) +>unique2 : Symbol(unique2, Decl(registeredSymbolPropertyAccess.ts, 4, 12)) + +wellKnownVal = record3[wellKnown] satisfies "wellKnown"; +>wellKnownVal : Symbol(wellKnownVal, Decl(registeredSymbolPropertyAccess.ts, 30, 10)) +>record3 : Symbol(record3, Decl(registeredSymbolPropertyAccess.ts, 32, 12)) +>wellKnown : Symbol(wellKnown, Decl(registeredSymbolPropertyAccess.ts, 5, 12)) + +export const record4 = { +>record4 : Symbol(record4, Decl(registeredSymbolPropertyAccess.ts, 46, 12)) + + [wellKnown2]: "wellKnown2", +>[wellKnown2] : Symbol([wellKnown2], Decl(registeredSymbolPropertyAccess.ts, 46, 24)) +>wellKnown2 : Symbol(wellKnown2, Decl(registeredSymbolPropertyAccess.ts, 6, 12)) + +} as const; +>const : Symbol(const) + +export let wellKnown2Val: string = record4[wellKnown2] satisfies "wellKnown2"; +>wellKnown2Val : Symbol(wellKnown2Val, Decl(registeredSymbolPropertyAccess.ts, 49, 10)) +>record4 : Symbol(record4, Decl(registeredSymbolPropertyAccess.ts, 46, 12)) +>wellKnown2 : Symbol(wellKnown2, Decl(registeredSymbolPropertyAccess.ts, 6, 12)) + diff --git a/testdata/baselines/reference/compiler/registeredSymbolPropertyAccess.types b/tsc/testdata/baselines/reference/compiler/registeredSymbolPropertyAccess.types similarity index 97% rename from testdata/baselines/reference/compiler/registeredSymbolPropertyAccess.types rename to tsc/testdata/baselines/reference/compiler/registeredSymbolPropertyAccess.types index 69ad18465418a..06cb06b09d07a 100644 --- a/testdata/baselines/reference/compiler/registeredSymbolPropertyAccess.types +++ b/tsc/testdata/baselines/reference/compiler/registeredSymbolPropertyAccess.types @@ -1,275 +1,275 @@ -//// [tests/cases/compiler/registeredSymbolPropertyAccess.ts] //// - -=== registeredSymbolPropertyAccess.ts === -export const single = Symbol.for("single"); ->single : RegisteredSymbol<"single"> ->Symbol.for("single") : RegisteredSymbol<"single"> ->Symbol.for : (key: Key) => RegisteredSymbol ->Symbol : SymbolConstructor ->for : (key: Key) => RegisteredSymbol ->"single" : "single" - -export const twin1 = Symbol.for("twin"); ->twin1 : RegisteredSymbol<"twin"> ->Symbol.for("twin") : RegisteredSymbol<"twin"> ->Symbol.for : (key: Key) => RegisteredSymbol ->Symbol : SymbolConstructor ->for : (key: Key) => RegisteredSymbol ->"twin" : "twin" - -export const twin2 = Symbol.for("twin"); ->twin2 : RegisteredSymbol<"twin"> ->Symbol.for("twin") : RegisteredSymbol<"twin"> ->Symbol.for : (key: Key) => RegisteredSymbol ->Symbol : SymbolConstructor ->for : (key: Key) => RegisteredSymbol ->"twin" : "twin" - -export const unique1 = Symbol("unique"); ->unique1 : unique symbol ->Symbol("unique") : unique symbol ->Symbol : SymbolConstructor ->"unique" : "unique" - -export const unique2 = Symbol("unique"); ->unique2 : unique symbol ->Symbol("unique") : unique symbol ->Symbol : SymbolConstructor ->"unique" : "unique" - -export const wellKnown = Symbol.match; ->wellKnown : unique symbol ->Symbol.match : unique symbol ->Symbol : SymbolConstructor ->match : unique symbol - -export const wellKnown2 = Symbol.toStringTag; ->wellKnown2 : unique symbol ->Symbol.toStringTag : unique symbol ->Symbol : SymbolConstructor ->toStringTag : unique symbol - -export const record1 = { ->record1 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique1]: "unique1"; readonly [unique2]: "unique2"; } ->{ [single]: "single", [twin2]: "twin", [unique1]: "unique1", [unique2]: "unique2",} as const : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique1]: "unique1"; readonly [unique2]: "unique2"; } ->{ [single]: "single", [twin2]: "twin", [unique1]: "unique1", [unique2]: "unique2",} : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique1]: "unique1"; readonly [unique2]: "unique2"; } - - [single]: "single", ->[single] : "single" ->single : RegisteredSymbol<"single"> ->"single" : "single" - - [twin2]: "twin", ->[twin2] : "twin" ->twin2 : RegisteredSymbol<"twin"> ->"twin" : "twin" - - [unique1]: "unique1", ->[unique1] : "unique1" ->unique1 : unique symbol ->"unique1" : "unique1" - - [unique2]: "unique2", ->[unique2] : "unique2" ->unique2 : unique symbol ->"unique2" : "unique2" - -} as const; -export let singleVal: string = record1[single] satisfies "single"; ->singleVal : string ->record1[single] satisfies "single" : "single" ->record1[single] : "single" ->record1 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique1]: "unique1"; readonly [unique2]: "unique2"; } ->single : RegisteredSymbol<"single"> - -export let twin1Val: string = record1[twin1] satisfies "twin"; ->twin1Val : string ->record1[twin1] satisfies "twin" : "twin" ->record1[twin1] : "twin" ->record1 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique1]: "unique1"; readonly [unique2]: "unique2"; } ->twin1 : RegisteredSymbol<"twin"> - -export let twin2Val: string = record1[twin2] satisfies "twin"; ->twin2Val : string ->record1[twin2] satisfies "twin" : "twin" ->record1[twin2] : "twin" ->record1 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique1]: "unique1"; readonly [unique2]: "unique2"; } ->twin2 : RegisteredSymbol<"twin"> - -export let unique1Val: string = record1[unique1] satisfies "unique1"; ->unique1Val : string ->record1[unique1] satisfies "unique1" : "unique1" ->record1[unique1] : "unique1" ->record1 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique1]: "unique1"; readonly [unique2]: "unique2"; } ->unique1 : unique symbol - -export let unique2Val: string = record1[unique2] satisfies "unique2"; ->unique2Val : string ->record1[unique2] satisfies "unique2" : "unique2" ->record1[unique2] : "unique2" ->record1 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique1]: "unique1"; readonly [unique2]: "unique2"; } ->unique2 : unique symbol - -export const record2 = { ->record2 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique2]: "unique2"; readonly [unique1]: "unique1New"; readonly [Symbol.match]: "wellKnown"; } ->{ ...record1, [unique1]: "unique1New", [wellKnown]: "wellKnown",} as const : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique2]: "unique2"; readonly [unique1]: "unique1New"; readonly [Symbol.match]: "wellKnown"; } ->{ ...record1, [unique1]: "unique1New", [wellKnown]: "wellKnown",} : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique2]: "unique2"; readonly [unique1]: "unique1New"; readonly [Symbol.match]: "wellKnown"; } - - ...record1, ->record1 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique1]: "unique1"; readonly [unique2]: "unique2"; } - - [unique1]: "unique1New", ->[unique1] : "unique1New" ->unique1 : unique symbol ->"unique1New" : "unique1New" - - [wellKnown]: "wellKnown", ->[wellKnown] : "wellKnown" ->wellKnown : unique symbol ->"wellKnown" : "wellKnown" - -} as const; -singleVal = record2[single] satisfies "single"; ->singleVal = record2[single] satisfies "single" : "single" ->singleVal : string ->record2[single] satisfies "single" : "single" ->record2[single] : "single" ->record2 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique2]: "unique2"; readonly [unique1]: "unique1New"; readonly [Symbol.match]: "wellKnown"; } ->single : RegisteredSymbol<"single"> - -twin1Val = record2[twin1] satisfies "twin"; ->twin1Val = record2[twin1] satisfies "twin" : "twin" ->twin1Val : string ->record2[twin1] satisfies "twin" : "twin" ->record2[twin1] : "twin" ->record2 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique2]: "unique2"; readonly [unique1]: "unique1New"; readonly [Symbol.match]: "wellKnown"; } ->twin1 : RegisteredSymbol<"twin"> - -twin2Val = record2[twin2] satisfies "twin"; ->twin2Val = record2[twin2] satisfies "twin" : "twin" ->twin2Val : string ->record2[twin2] satisfies "twin" : "twin" ->record2[twin2] : "twin" ->record2 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique2]: "unique2"; readonly [unique1]: "unique1New"; readonly [Symbol.match]: "wellKnown"; } ->twin2 : RegisteredSymbol<"twin"> - -unique1Val = record2[unique1] satisfies "unique1New"; ->unique1Val = record2[unique1] satisfies "unique1New" : "unique1New" ->unique1Val : string ->record2[unique1] satisfies "unique1New" : "unique1New" ->record2[unique1] : "unique1New" ->record2 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique2]: "unique2"; readonly [unique1]: "unique1New"; readonly [Symbol.match]: "wellKnown"; } ->unique1 : unique symbol - -unique2Val = record2[unique2] satisfies "unique2"; ->unique2Val = record2[unique2] satisfies "unique2" : "unique2" ->unique2Val : string ->record2[unique2] satisfies "unique2" : "unique2" ->record2[unique2] : "unique2" ->record2 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique2]: "unique2"; readonly [unique1]: "unique1New"; readonly [Symbol.match]: "wellKnown"; } ->unique2 : unique symbol - -export let wellKnownVal: string = record2[wellKnown] satisfies "wellKnown"; ->wellKnownVal : string ->record2[wellKnown] satisfies "wellKnown" : "wellKnown" ->record2[wellKnown] : "wellKnown" ->record2 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique2]: "unique2"; readonly [unique1]: "unique1New"; readonly [Symbol.match]: "wellKnown"; } ->wellKnown : unique symbol - -export const record3 = { ->record3 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique1]: "unique1"; readonly [unique2]: "unique2"; readonly [Symbol.match]: "wellKnown"; } ->{ [single]: "single", [twin2]: "twin", [unique1]: "unique1", [unique2]: "unique2", [wellKnown]: "wellKnown",} as const : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique1]: "unique1"; readonly [unique2]: "unique2"; readonly [Symbol.match]: "wellKnown"; } ->{ [single]: "single", [twin2]: "twin", [unique1]: "unique1", [unique2]: "unique2", [wellKnown]: "wellKnown",} : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique1]: "unique1"; readonly [unique2]: "unique2"; readonly [Symbol.match]: "wellKnown"; } - - [single]: "single", ->[single] : "single" ->single : RegisteredSymbol<"single"> ->"single" : "single" - - [twin2]: "twin", ->[twin2] : "twin" ->twin2 : RegisteredSymbol<"twin"> ->"twin" : "twin" - - [unique1]: "unique1", ->[unique1] : "unique1" ->unique1 : unique symbol ->"unique1" : "unique1" - - [unique2]: "unique2", ->[unique2] : "unique2" ->unique2 : unique symbol ->"unique2" : "unique2" - - [wellKnown]: "wellKnown", ->[wellKnown] : "wellKnown" ->wellKnown : unique symbol ->"wellKnown" : "wellKnown" - -} as const; -singleVal = record3[single] satisfies "single"; ->singleVal = record3[single] satisfies "single" : "single" ->singleVal : string ->record3[single] satisfies "single" : "single" ->record3[single] : "single" ->record3 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique1]: "unique1"; readonly [unique2]: "unique2"; readonly [Symbol.match]: "wellKnown"; } ->single : RegisteredSymbol<"single"> - -twin1Val = record3[twin1] satisfies "twin"; ->twin1Val = record3[twin1] satisfies "twin" : "twin" ->twin1Val : string ->record3[twin1] satisfies "twin" : "twin" ->record3[twin1] : "twin" ->record3 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique1]: "unique1"; readonly [unique2]: "unique2"; readonly [Symbol.match]: "wellKnown"; } ->twin1 : RegisteredSymbol<"twin"> - -twin2Val = record3[twin2] satisfies "twin"; ->twin2Val = record3[twin2] satisfies "twin" : "twin" ->twin2Val : string ->record3[twin2] satisfies "twin" : "twin" ->record3[twin2] : "twin" ->record3 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique1]: "unique1"; readonly [unique2]: "unique2"; readonly [Symbol.match]: "wellKnown"; } ->twin2 : RegisteredSymbol<"twin"> - -unique1Val = record3[unique1] satisfies "unique1"; ->unique1Val = record3[unique1] satisfies "unique1" : "unique1" ->unique1Val : string ->record3[unique1] satisfies "unique1" : "unique1" ->record3[unique1] : "unique1" ->record3 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique1]: "unique1"; readonly [unique2]: "unique2"; readonly [Symbol.match]: "wellKnown"; } ->unique1 : unique symbol - -unique2Val = record3[unique2] satisfies "unique2"; ->unique2Val = record3[unique2] satisfies "unique2" : "unique2" ->unique2Val : string ->record3[unique2] satisfies "unique2" : "unique2" ->record3[unique2] : "unique2" ->record3 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique1]: "unique1"; readonly [unique2]: "unique2"; readonly [Symbol.match]: "wellKnown"; } ->unique2 : unique symbol - -wellKnownVal = record3[wellKnown] satisfies "wellKnown"; ->wellKnownVal = record3[wellKnown] satisfies "wellKnown" : "wellKnown" ->wellKnownVal : string ->record3[wellKnown] satisfies "wellKnown" : "wellKnown" ->record3[wellKnown] : "wellKnown" ->record3 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique1]: "unique1"; readonly [unique2]: "unique2"; readonly [Symbol.match]: "wellKnown"; } ->wellKnown : unique symbol - -export const record4 = { ->record4 : { readonly [Symbol.toStringTag]: "wellKnown2"; } ->{ [wellKnown2]: "wellKnown2",} as const : { readonly [Symbol.toStringTag]: "wellKnown2"; } ->{ [wellKnown2]: "wellKnown2",} : { readonly [Symbol.toStringTag]: "wellKnown2"; } - - [wellKnown2]: "wellKnown2", ->[wellKnown2] : "wellKnown2" ->wellKnown2 : unique symbol ->"wellKnown2" : "wellKnown2" - -} as const; -export let wellKnown2Val: string = record4[wellKnown2] satisfies "wellKnown2"; ->wellKnown2Val : string ->record4[wellKnown2] satisfies "wellKnown2" : "wellKnown2" ->record4[wellKnown2] : "wellKnown2" ->record4 : { readonly [Symbol.toStringTag]: "wellKnown2"; } ->wellKnown2 : unique symbol - +//// [tests/cases/compiler/registeredSymbolPropertyAccess.ts] //// + +=== registeredSymbolPropertyAccess.ts === +export const single = Symbol.for("single"); +>single : RegisteredSymbol<"single"> +>Symbol.for("single") : RegisteredSymbol<"single"> +>Symbol.for : (key: Key) => RegisteredSymbol +>Symbol : SymbolConstructor +>for : (key: Key) => RegisteredSymbol +>"single" : "single" + +export const twin1 = Symbol.for("twin"); +>twin1 : RegisteredSymbol<"twin"> +>Symbol.for("twin") : RegisteredSymbol<"twin"> +>Symbol.for : (key: Key) => RegisteredSymbol +>Symbol : SymbolConstructor +>for : (key: Key) => RegisteredSymbol +>"twin" : "twin" + +export const twin2 = Symbol.for("twin"); +>twin2 : RegisteredSymbol<"twin"> +>Symbol.for("twin") : RegisteredSymbol<"twin"> +>Symbol.for : (key: Key) => RegisteredSymbol +>Symbol : SymbolConstructor +>for : (key: Key) => RegisteredSymbol +>"twin" : "twin" + +export const unique1 = Symbol("unique"); +>unique1 : unique symbol +>Symbol("unique") : unique symbol +>Symbol : SymbolConstructor +>"unique" : "unique" + +export const unique2 = Symbol("unique"); +>unique2 : unique symbol +>Symbol("unique") : unique symbol +>Symbol : SymbolConstructor +>"unique" : "unique" + +export const wellKnown = Symbol.match; +>wellKnown : unique symbol +>Symbol.match : unique symbol +>Symbol : SymbolConstructor +>match : unique symbol + +export const wellKnown2 = Symbol.toStringTag; +>wellKnown2 : unique symbol +>Symbol.toStringTag : unique symbol +>Symbol : SymbolConstructor +>toStringTag : unique symbol + +export const record1 = { +>record1 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique1]: "unique1"; readonly [unique2]: "unique2"; } +>{ [single]: "single", [twin2]: "twin", [unique1]: "unique1", [unique2]: "unique2",} as const : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique1]: "unique1"; readonly [unique2]: "unique2"; } +>{ [single]: "single", [twin2]: "twin", [unique1]: "unique1", [unique2]: "unique2",} : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique1]: "unique1"; readonly [unique2]: "unique2"; } + + [single]: "single", +>[single] : "single" +>single : RegisteredSymbol<"single"> +>"single" : "single" + + [twin2]: "twin", +>[twin2] : "twin" +>twin2 : RegisteredSymbol<"twin"> +>"twin" : "twin" + + [unique1]: "unique1", +>[unique1] : "unique1" +>unique1 : unique symbol +>"unique1" : "unique1" + + [unique2]: "unique2", +>[unique2] : "unique2" +>unique2 : unique symbol +>"unique2" : "unique2" + +} as const; +export let singleVal: string = record1[single] satisfies "single"; +>singleVal : string +>record1[single] satisfies "single" : "single" +>record1[single] : "single" +>record1 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique1]: "unique1"; readonly [unique2]: "unique2"; } +>single : RegisteredSymbol<"single"> + +export let twin1Val: string = record1[twin1] satisfies "twin"; +>twin1Val : string +>record1[twin1] satisfies "twin" : "twin" +>record1[twin1] : "twin" +>record1 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique1]: "unique1"; readonly [unique2]: "unique2"; } +>twin1 : RegisteredSymbol<"twin"> + +export let twin2Val: string = record1[twin2] satisfies "twin"; +>twin2Val : string +>record1[twin2] satisfies "twin" : "twin" +>record1[twin2] : "twin" +>record1 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique1]: "unique1"; readonly [unique2]: "unique2"; } +>twin2 : RegisteredSymbol<"twin"> + +export let unique1Val: string = record1[unique1] satisfies "unique1"; +>unique1Val : string +>record1[unique1] satisfies "unique1" : "unique1" +>record1[unique1] : "unique1" +>record1 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique1]: "unique1"; readonly [unique2]: "unique2"; } +>unique1 : unique symbol + +export let unique2Val: string = record1[unique2] satisfies "unique2"; +>unique2Val : string +>record1[unique2] satisfies "unique2" : "unique2" +>record1[unique2] : "unique2" +>record1 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique1]: "unique1"; readonly [unique2]: "unique2"; } +>unique2 : unique symbol + +export const record2 = { +>record2 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique2]: "unique2"; readonly [unique1]: "unique1New"; readonly [Symbol.match]: "wellKnown"; } +>{ ...record1, [unique1]: "unique1New", [wellKnown]: "wellKnown",} as const : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique2]: "unique2"; readonly [unique1]: "unique1New"; readonly [Symbol.match]: "wellKnown"; } +>{ ...record1, [unique1]: "unique1New", [wellKnown]: "wellKnown",} : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique2]: "unique2"; readonly [unique1]: "unique1New"; readonly [Symbol.match]: "wellKnown"; } + + ...record1, +>record1 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique1]: "unique1"; readonly [unique2]: "unique2"; } + + [unique1]: "unique1New", +>[unique1] : "unique1New" +>unique1 : unique symbol +>"unique1New" : "unique1New" + + [wellKnown]: "wellKnown", +>[wellKnown] : "wellKnown" +>wellKnown : unique symbol +>"wellKnown" : "wellKnown" + +} as const; +singleVal = record2[single] satisfies "single"; +>singleVal = record2[single] satisfies "single" : "single" +>singleVal : string +>record2[single] satisfies "single" : "single" +>record2[single] : "single" +>record2 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique2]: "unique2"; readonly [unique1]: "unique1New"; readonly [Symbol.match]: "wellKnown"; } +>single : RegisteredSymbol<"single"> + +twin1Val = record2[twin1] satisfies "twin"; +>twin1Val = record2[twin1] satisfies "twin" : "twin" +>twin1Val : string +>record2[twin1] satisfies "twin" : "twin" +>record2[twin1] : "twin" +>record2 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique2]: "unique2"; readonly [unique1]: "unique1New"; readonly [Symbol.match]: "wellKnown"; } +>twin1 : RegisteredSymbol<"twin"> + +twin2Val = record2[twin2] satisfies "twin"; +>twin2Val = record2[twin2] satisfies "twin" : "twin" +>twin2Val : string +>record2[twin2] satisfies "twin" : "twin" +>record2[twin2] : "twin" +>record2 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique2]: "unique2"; readonly [unique1]: "unique1New"; readonly [Symbol.match]: "wellKnown"; } +>twin2 : RegisteredSymbol<"twin"> + +unique1Val = record2[unique1] satisfies "unique1New"; +>unique1Val = record2[unique1] satisfies "unique1New" : "unique1New" +>unique1Val : string +>record2[unique1] satisfies "unique1New" : "unique1New" +>record2[unique1] : "unique1New" +>record2 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique2]: "unique2"; readonly [unique1]: "unique1New"; readonly [Symbol.match]: "wellKnown"; } +>unique1 : unique symbol + +unique2Val = record2[unique2] satisfies "unique2"; +>unique2Val = record2[unique2] satisfies "unique2" : "unique2" +>unique2Val : string +>record2[unique2] satisfies "unique2" : "unique2" +>record2[unique2] : "unique2" +>record2 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique2]: "unique2"; readonly [unique1]: "unique1New"; readonly [Symbol.match]: "wellKnown"; } +>unique2 : unique symbol + +export let wellKnownVal: string = record2[wellKnown] satisfies "wellKnown"; +>wellKnownVal : string +>record2[wellKnown] satisfies "wellKnown" : "wellKnown" +>record2[wellKnown] : "wellKnown" +>record2 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique2]: "unique2"; readonly [unique1]: "unique1New"; readonly [Symbol.match]: "wellKnown"; } +>wellKnown : unique symbol + +export const record3 = { +>record3 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique1]: "unique1"; readonly [unique2]: "unique2"; readonly [Symbol.match]: "wellKnown"; } +>{ [single]: "single", [twin2]: "twin", [unique1]: "unique1", [unique2]: "unique2", [wellKnown]: "wellKnown",} as const : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique1]: "unique1"; readonly [unique2]: "unique2"; readonly [Symbol.match]: "wellKnown"; } +>{ [single]: "single", [twin2]: "twin", [unique1]: "unique1", [unique2]: "unique2", [wellKnown]: "wellKnown",} : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique1]: "unique1"; readonly [unique2]: "unique2"; readonly [Symbol.match]: "wellKnown"; } + + [single]: "single", +>[single] : "single" +>single : RegisteredSymbol<"single"> +>"single" : "single" + + [twin2]: "twin", +>[twin2] : "twin" +>twin2 : RegisteredSymbol<"twin"> +>"twin" : "twin" + + [unique1]: "unique1", +>[unique1] : "unique1" +>unique1 : unique symbol +>"unique1" : "unique1" + + [unique2]: "unique2", +>[unique2] : "unique2" +>unique2 : unique symbol +>"unique2" : "unique2" + + [wellKnown]: "wellKnown", +>[wellKnown] : "wellKnown" +>wellKnown : unique symbol +>"wellKnown" : "wellKnown" + +} as const; +singleVal = record3[single] satisfies "single"; +>singleVal = record3[single] satisfies "single" : "single" +>singleVal : string +>record3[single] satisfies "single" : "single" +>record3[single] : "single" +>record3 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique1]: "unique1"; readonly [unique2]: "unique2"; readonly [Symbol.match]: "wellKnown"; } +>single : RegisteredSymbol<"single"> + +twin1Val = record3[twin1] satisfies "twin"; +>twin1Val = record3[twin1] satisfies "twin" : "twin" +>twin1Val : string +>record3[twin1] satisfies "twin" : "twin" +>record3[twin1] : "twin" +>record3 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique1]: "unique1"; readonly [unique2]: "unique2"; readonly [Symbol.match]: "wellKnown"; } +>twin1 : RegisteredSymbol<"twin"> + +twin2Val = record3[twin2] satisfies "twin"; +>twin2Val = record3[twin2] satisfies "twin" : "twin" +>twin2Val : string +>record3[twin2] satisfies "twin" : "twin" +>record3[twin2] : "twin" +>record3 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique1]: "unique1"; readonly [unique2]: "unique2"; readonly [Symbol.match]: "wellKnown"; } +>twin2 : RegisteredSymbol<"twin"> + +unique1Val = record3[unique1] satisfies "unique1"; +>unique1Val = record3[unique1] satisfies "unique1" : "unique1" +>unique1Val : string +>record3[unique1] satisfies "unique1" : "unique1" +>record3[unique1] : "unique1" +>record3 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique1]: "unique1"; readonly [unique2]: "unique2"; readonly [Symbol.match]: "wellKnown"; } +>unique1 : unique symbol + +unique2Val = record3[unique2] satisfies "unique2"; +>unique2Val = record3[unique2] satisfies "unique2" : "unique2" +>unique2Val : string +>record3[unique2] satisfies "unique2" : "unique2" +>record3[unique2] : "unique2" +>record3 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique1]: "unique1"; readonly [unique2]: "unique2"; readonly [Symbol.match]: "wellKnown"; } +>unique2 : unique symbol + +wellKnownVal = record3[wellKnown] satisfies "wellKnown"; +>wellKnownVal = record3[wellKnown] satisfies "wellKnown" : "wellKnown" +>wellKnownVal : string +>record3[wellKnown] satisfies "wellKnown" : "wellKnown" +>record3[wellKnown] : "wellKnown" +>record3 : { readonly [single]: "single"; readonly [twin2]: "twin"; readonly [unique1]: "unique1"; readonly [unique2]: "unique2"; readonly [Symbol.match]: "wellKnown"; } +>wellKnown : unique symbol + +export const record4 = { +>record4 : { readonly [Symbol.toStringTag]: "wellKnown2"; } +>{ [wellKnown2]: "wellKnown2",} as const : { readonly [Symbol.toStringTag]: "wellKnown2"; } +>{ [wellKnown2]: "wellKnown2",} : { readonly [Symbol.toStringTag]: "wellKnown2"; } + + [wellKnown2]: "wellKnown2", +>[wellKnown2] : "wellKnown2" +>wellKnown2 : unique symbol +>"wellKnown2" : "wellKnown2" + +} as const; +export let wellKnown2Val: string = record4[wellKnown2] satisfies "wellKnown2"; +>wellKnown2Val : string +>record4[wellKnown2] satisfies "wellKnown2" : "wellKnown2" +>record4[wellKnown2] : "wellKnown2" +>record4 : { readonly [Symbol.toStringTag]: "wellKnown2"; } +>wellKnown2 : unique symbol + diff --git a/testdata/baselines/reference/compiler/uniqueSymbolConstLikeWidening.symbols b/tsc/testdata/baselines/reference/compiler/uniqueSymbolConstLikeWidening.symbols similarity index 97% rename from testdata/baselines/reference/compiler/uniqueSymbolConstLikeWidening.symbols rename to tsc/testdata/baselines/reference/compiler/uniqueSymbolConstLikeWidening.symbols index 1aac2b9272522..ef40851edcdde 100644 --- a/testdata/baselines/reference/compiler/uniqueSymbolConstLikeWidening.symbols +++ b/tsc/testdata/baselines/reference/compiler/uniqueSymbolConstLikeWidening.symbols @@ -1,40 +1,40 @@ -//// [tests/cases/compiler/uniqueSymbolConstLikeWidening.ts] //// - -=== uniqueSymbolConstLikeWidening.ts === -const us = Symbol.match; ->us : Symbol(us, Decl(uniqueSymbolConstLikeWidening.ts, 0, 5)) ->Symbol.match : Symbol(SymbolConstructor.match, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) ->Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) ->match : Symbol(SymbolConstructor.match, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) - -const us2 = us; ->us2 : Symbol(us2, Decl(uniqueSymbolConstLikeWidening.ts, 1, 5)) ->us : Symbol(us, Decl(uniqueSymbolConstLikeWidening.ts, 0, 5)) - -let widened = us; ->widened : Symbol(widened, Decl(uniqueSymbolConstLikeWidening.ts, 2, 3)) ->us : Symbol(us, Decl(uniqueSymbolConstLikeWidening.ts, 0, 5)) - -let asserted = us as const; ->asserted : Symbol(asserted, Decl(uniqueSymbolConstLikeWidening.ts, 3, 3)) ->us : Symbol(us, Decl(uniqueSymbolConstLikeWidening.ts, 0, 5)) ->const : Symbol(const) - -let sameAsSource: typeof us = us2; ->sameAsSource : Symbol(sameAsSource, Decl(uniqueSymbolConstLikeWidening.ts, 5, 3)) ->us : Symbol(us, Decl(uniqueSymbolConstLikeWidening.ts, 0, 5)) ->us2 : Symbol(us2, Decl(uniqueSymbolConstLikeWidening.ts, 1, 5)) - -let sameAsAsserted: typeof us = asserted; ->sameAsAsserted : Symbol(sameAsAsserted, Decl(uniqueSymbolConstLikeWidening.ts, 6, 3)) ->us : Symbol(us, Decl(uniqueSymbolConstLikeWidening.ts, 0, 5)) ->asserted : Symbol(asserted, Decl(uniqueSymbolConstLikeWidening.ts, 3, 3)) - -let symbolFromConst: symbol = us2; ->symbolFromConst : Symbol(symbolFromConst, Decl(uniqueSymbolConstLikeWidening.ts, 7, 3)) ->us2 : Symbol(us2, Decl(uniqueSymbolConstLikeWidening.ts, 1, 5)) - -let symbolFromAsserted: symbol = asserted; ->symbolFromAsserted : Symbol(symbolFromAsserted, Decl(uniqueSymbolConstLikeWidening.ts, 8, 3)) ->asserted : Symbol(asserted, Decl(uniqueSymbolConstLikeWidening.ts, 3, 3)) - +//// [tests/cases/compiler/uniqueSymbolConstLikeWidening.ts] //// + +=== uniqueSymbolConstLikeWidening.ts === +const us = Symbol.match; +>us : Symbol(us, Decl(uniqueSymbolConstLikeWidening.ts, 0, 5)) +>Symbol.match : Symbol(SymbolConstructor.match, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>match : Symbol(SymbolConstructor.match, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + +const us2 = us; +>us2 : Symbol(us2, Decl(uniqueSymbolConstLikeWidening.ts, 1, 5)) +>us : Symbol(us, Decl(uniqueSymbolConstLikeWidening.ts, 0, 5)) + +let widened = us; +>widened : Symbol(widened, Decl(uniqueSymbolConstLikeWidening.ts, 2, 3)) +>us : Symbol(us, Decl(uniqueSymbolConstLikeWidening.ts, 0, 5)) + +let asserted = us as const; +>asserted : Symbol(asserted, Decl(uniqueSymbolConstLikeWidening.ts, 3, 3)) +>us : Symbol(us, Decl(uniqueSymbolConstLikeWidening.ts, 0, 5)) +>const : Symbol(const) + +let sameAsSource: typeof us = us2; +>sameAsSource : Symbol(sameAsSource, Decl(uniqueSymbolConstLikeWidening.ts, 5, 3)) +>us : Symbol(us, Decl(uniqueSymbolConstLikeWidening.ts, 0, 5)) +>us2 : Symbol(us2, Decl(uniqueSymbolConstLikeWidening.ts, 1, 5)) + +let sameAsAsserted: typeof us = asserted; +>sameAsAsserted : Symbol(sameAsAsserted, Decl(uniqueSymbolConstLikeWidening.ts, 6, 3)) +>us : Symbol(us, Decl(uniqueSymbolConstLikeWidening.ts, 0, 5)) +>asserted : Symbol(asserted, Decl(uniqueSymbolConstLikeWidening.ts, 3, 3)) + +let symbolFromConst: symbol = us2; +>symbolFromConst : Symbol(symbolFromConst, Decl(uniqueSymbolConstLikeWidening.ts, 7, 3)) +>us2 : Symbol(us2, Decl(uniqueSymbolConstLikeWidening.ts, 1, 5)) + +let symbolFromAsserted: symbol = asserted; +>symbolFromAsserted : Symbol(symbolFromAsserted, Decl(uniqueSymbolConstLikeWidening.ts, 8, 3)) +>asserted : Symbol(asserted, Decl(uniqueSymbolConstLikeWidening.ts, 3, 3)) + diff --git a/testdata/baselines/reference/compiler/uniqueSymbolConstLikeWidening.types b/tsc/testdata/baselines/reference/compiler/uniqueSymbolConstLikeWidening.types similarity index 95% rename from testdata/baselines/reference/compiler/uniqueSymbolConstLikeWidening.types rename to tsc/testdata/baselines/reference/compiler/uniqueSymbolConstLikeWidening.types index 98d7ed64ab4d0..17cdf95bf699a 100644 --- a/testdata/baselines/reference/compiler/uniqueSymbolConstLikeWidening.types +++ b/tsc/testdata/baselines/reference/compiler/uniqueSymbolConstLikeWidening.types @@ -1,40 +1,40 @@ -//// [tests/cases/compiler/uniqueSymbolConstLikeWidening.ts] //// - -=== uniqueSymbolConstLikeWidening.ts === -const us = Symbol.match; ->us : unique symbol ->Symbol.match : unique symbol ->Symbol : SymbolConstructor ->match : unique symbol - -const us2 = us; ->us2 : unique symbol ->us : unique symbol - -let widened = us; ->widened : symbol ->us : unique symbol - -let asserted = us as const; ->asserted : unique symbol ->us as const : unique symbol ->us : unique symbol - -let sameAsSource: typeof us = us2; ->sameAsSource : unique symbol ->us : unique symbol ->us2 : unique symbol - -let sameAsAsserted: typeof us = asserted; ->sameAsAsserted : unique symbol ->us : unique symbol ->asserted : unique symbol - -let symbolFromConst: symbol = us2; ->symbolFromConst : symbol ->us2 : unique symbol - -let symbolFromAsserted: symbol = asserted; ->symbolFromAsserted : symbol ->asserted : unique symbol - +//// [tests/cases/compiler/uniqueSymbolConstLikeWidening.ts] //// + +=== uniqueSymbolConstLikeWidening.ts === +const us = Symbol.match; +>us : unique symbol +>Symbol.match : unique symbol +>Symbol : SymbolConstructor +>match : unique symbol + +const us2 = us; +>us2 : unique symbol +>us : unique symbol + +let widened = us; +>widened : symbol +>us : unique symbol + +let asserted = us as const; +>asserted : unique symbol +>us as const : unique symbol +>us : unique symbol + +let sameAsSource: typeof us = us2; +>sameAsSource : unique symbol +>us : unique symbol +>us2 : unique symbol + +let sameAsAsserted: typeof us = asserted; +>sameAsAsserted : unique symbol +>us : unique symbol +>asserted : unique symbol + +let symbolFromConst: symbol = us2; +>symbolFromConst : symbol +>us2 : unique symbol + +let symbolFromAsserted: symbol = asserted; +>symbolFromAsserted : symbol +>asserted : unique symbol + diff --git a/testdata/tests/cases/compiler/registeredSymbolIntrinsic.ts b/tsc/testdata/tests/cases/compiler/registeredSymbolIntrinsic.ts similarity index 100% rename from testdata/tests/cases/compiler/registeredSymbolIntrinsic.ts rename to tsc/testdata/tests/cases/compiler/registeredSymbolIntrinsic.ts diff --git a/testdata/tests/cases/compiler/registeredSymbolPropertyAccess.ts b/tsc/testdata/tests/cases/compiler/registeredSymbolPropertyAccess.ts similarity index 100% rename from testdata/tests/cases/compiler/registeredSymbolPropertyAccess.ts rename to tsc/testdata/tests/cases/compiler/registeredSymbolPropertyAccess.ts diff --git a/testdata/tests/cases/compiler/uniqueSymbolConstLikeWidening.ts b/tsc/testdata/tests/cases/compiler/uniqueSymbolConstLikeWidening.ts similarity index 100% rename from testdata/tests/cases/compiler/uniqueSymbolConstLikeWidening.ts rename to tsc/testdata/tests/cases/compiler/uniqueSymbolConstLikeWidening.ts From 9d2d9e6e5cb2e07ce90807e042b9d16f8b459ce9 Mon Sep 17 00:00:00 2001 From: Michael FIG Date: Fri, 25 Sep 2026 14:29:31 -0600 Subject: [PATCH 5/6] Avoid unique symbol identities for broad registry keys Resolve broad registered-symbol keys to symbol and distribute literal union keys over their possible registered symbol identities. Add compiler coverage for both cases. Co-authored-by: Codex --- tsc/internal/checker/checker.go | 16 +++++++++ .../registeredSymbolIntrinsic.errors.txt | 34 +++++++++++++++++++ .../registeredSymbolIntrinsic.symbols | 34 +++++++++++++++++-- .../compiler/registeredSymbolIntrinsic.types | 33 ++++++++++++++++-- .../compiler/registeredSymbolIntrinsic.ts | 6 ++++ 5 files changed, 118 insertions(+), 5 deletions(-) create mode 100644 tsc/testdata/baselines/reference/compiler/registeredSymbolIntrinsic.errors.txt diff --git a/tsc/internal/checker/checker.go b/tsc/internal/checker/checker.go index 0d7e12da4e80f..e952983ccbcb4 100644 --- a/tsc/internal/checker/checker.go +++ b/tsc/internal/checker/checker.go @@ -23374,6 +23374,22 @@ func (c *Checker) getESSymbolLikeTypeForNode(node *ast.Node) *Type { } func (c *Checker) getRegisteredESSymbolType(keyType *Type, alias *TypeAlias) *Type { + if keyType.flags&TypeFlagsUnion != 0 { + members := make([]*Type, 0, len(keyType.Types())) + for _, member := range keyType.Types() { + if member.flags&TypeFlagsStringOrNumberLiteral == 0 { + return c.esSymbolType + } + memberAlias := &TypeAlias{symbol: alias.symbol, typeArguments: []*Type{member}} + members = append(members, c.getRegisteredESSymbolType(member, memberAlias)) + } + return c.getUnionType(members) + } + // Keep a type parameter deferred so instantiating Symbol.for's generic + // return type can resolve the actual key supplied at the call site. + if keyType.flags&(TypeFlagsStringOrNumberLiteral|TypeFlagsTypeParameter) == 0 { + return c.esSymbolType + } key := c.getRegisteredESSymbolTypeKey(keyType) t := c.registeredESSymbolTypes[key] if t == nil { diff --git a/tsc/testdata/baselines/reference/compiler/registeredSymbolIntrinsic.errors.txt b/tsc/testdata/baselines/reference/compiler/registeredSymbolIntrinsic.errors.txt new file mode 100644 index 0000000000000..3df1f07aa86e0 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/registeredSymbolIntrinsic.errors.txt @@ -0,0 +1,34 @@ +registeredSymbolIntrinsic.ts(13,5): error TS2322: Type 'symbol' is not assignable to type 'RegisteredSymbol<"foo">'. +registeredSymbolIntrinsic.ts(17,5): error TS2322: Type 'RegisteredSymbol<"bar"> | RegisteredSymbol<"foo">' is not assignable to type 'RegisteredSymbol<"foo">'. + Type 'RegisteredSymbol<"bar">' is not assignable to type 'RegisteredSymbol<"foo">'. + + +==== registeredSymbolIntrinsic.ts (2 errors) ==== + const foo = Symbol.for("foo"); + const fooAgain = Symbol.for("foo"); + const bar = Symbol.for("bar"); + + let sameStringKey: typeof foo = fooAgain; + let registeredStringKey: RegisteredSymbol<"foo"> = foo; + let registeredBarKey: RegisteredSymbol<"bar"> = bar; + let widenedSymbol: symbol = foo; + + declare const key: string; + let registeredString: RegisteredSymbol = Symbol.for(key); + let dynamic = Symbol.for(key); + let invalidDynamicKey: typeof foo = dynamic; + ~~~~~~~~~~~~~~~~~ +!!! error TS2322: Type 'symbol' is not assignable to type 'RegisteredSymbol<"foo">'. + + declare const unionKey: "foo" | "bar"; + let registeredUnion: RegisteredSymbol<"foo" | "bar"> = Symbol.for(unionKey); + let invalidUnionKey: typeof foo = registeredUnion; + ~~~~~~~~~~~~~~~ +!!! error TS2322: Type 'RegisteredSymbol<"bar"> | RegisteredSymbol<"foo">' is not assignable to type 'RegisteredSymbol<"foo">'. +!!! error TS2322: Type 'RegisteredSymbol<"bar">' is not assignable to type 'RegisteredSymbol<"foo">'. + + interface WithRegisteredKeys { + [foo]: string; + [bar]: number; + } + \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/compiler/registeredSymbolIntrinsic.symbols b/tsc/testdata/baselines/reference/compiler/registeredSymbolIntrinsic.symbols index 464849c20f266..a7feea4365e28 100644 --- a/tsc/testdata/baselines/reference/compiler/registeredSymbolIntrinsic.symbols +++ b/tsc/testdata/baselines/reference/compiler/registeredSymbolIntrinsic.symbols @@ -49,15 +49,43 @@ let registeredString: RegisteredSymbol = Symbol.for(key); >for : Symbol(SymbolConstructor.for, Decl(lib.es2015.symbol.d.ts, --, --)) >key : Symbol(key, Decl(registeredSymbolIntrinsic.ts, 9, 13)) +let dynamic = Symbol.for(key); +>dynamic : Symbol(dynamic, Decl(registeredSymbolIntrinsic.ts, 11, 3)) +>Symbol.for : Symbol(SymbolConstructor.for, Decl(lib.es2015.symbol.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>for : Symbol(SymbolConstructor.for, Decl(lib.es2015.symbol.d.ts, --, --)) +>key : Symbol(key, Decl(registeredSymbolIntrinsic.ts, 9, 13)) + +let invalidDynamicKey: typeof foo = dynamic; +>invalidDynamicKey : Symbol(invalidDynamicKey, Decl(registeredSymbolIntrinsic.ts, 12, 3)) +>foo : Symbol(foo, Decl(registeredSymbolIntrinsic.ts, 0, 5)) +>dynamic : Symbol(dynamic, Decl(registeredSymbolIntrinsic.ts, 11, 3)) + +declare const unionKey: "foo" | "bar"; +>unionKey : Symbol(unionKey, Decl(registeredSymbolIntrinsic.ts, 14, 13)) + +let registeredUnion: RegisteredSymbol<"foo" | "bar"> = Symbol.for(unionKey); +>registeredUnion : Symbol(registeredUnion, Decl(registeredSymbolIntrinsic.ts, 15, 3)) +>RegisteredSymbol : Symbol(RegisteredSymbol, Decl(lib.es2015.symbol.d.ts, --, --)) +>Symbol.for : Symbol(SymbolConstructor.for, Decl(lib.es2015.symbol.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>for : Symbol(SymbolConstructor.for, Decl(lib.es2015.symbol.d.ts, --, --)) +>unionKey : Symbol(unionKey, Decl(registeredSymbolIntrinsic.ts, 14, 13)) + +let invalidUnionKey: typeof foo = registeredUnion; +>invalidUnionKey : Symbol(invalidUnionKey, Decl(registeredSymbolIntrinsic.ts, 16, 3)) +>foo : Symbol(foo, Decl(registeredSymbolIntrinsic.ts, 0, 5)) +>registeredUnion : Symbol(registeredUnion, Decl(registeredSymbolIntrinsic.ts, 15, 3)) + interface WithRegisteredKeys { ->WithRegisteredKeys : Symbol(WithRegisteredKeys, Decl(registeredSymbolIntrinsic.ts, 10, 65)) +>WithRegisteredKeys : Symbol(WithRegisteredKeys, Decl(registeredSymbolIntrinsic.ts, 16, 50)) [foo]: string; ->[foo] : Symbol(WithRegisteredKeys[foo], Decl(registeredSymbolIntrinsic.ts, 12, 30)) +>[foo] : Symbol(WithRegisteredKeys[foo], Decl(registeredSymbolIntrinsic.ts, 18, 30)) >foo : Symbol(foo, Decl(registeredSymbolIntrinsic.ts, 0, 5)) [bar]: number; ->[bar] : Symbol(WithRegisteredKeys[bar], Decl(registeredSymbolIntrinsic.ts, 13, 18)) +>[bar] : Symbol(WithRegisteredKeys[bar], Decl(registeredSymbolIntrinsic.ts, 19, 18)) >bar : Symbol(bar, Decl(registeredSymbolIntrinsic.ts, 2, 5)) } diff --git a/tsc/testdata/baselines/reference/compiler/registeredSymbolIntrinsic.types b/tsc/testdata/baselines/reference/compiler/registeredSymbolIntrinsic.types index 8129e7620ae39..bf19d3a392e6c 100644 --- a/tsc/testdata/baselines/reference/compiler/registeredSymbolIntrinsic.types +++ b/tsc/testdata/baselines/reference/compiler/registeredSymbolIntrinsic.types @@ -46,13 +46,42 @@ declare const key: string; >key : string let registeredString: RegisteredSymbol = Symbol.for(key); ->registeredString : RegisteredSymbol ->Symbol.for(key) : RegisteredSymbol +>registeredString : symbol +>Symbol.for(key) : symbol >Symbol.for : (key: Key) => RegisteredSymbol >Symbol : SymbolConstructor >for : (key: Key) => RegisteredSymbol >key : string +let dynamic = Symbol.for(key); +>dynamic : symbol +>Symbol.for(key) : symbol +>Symbol.for : (key: Key) => RegisteredSymbol +>Symbol : SymbolConstructor +>for : (key: Key) => RegisteredSymbol +>key : string + +let invalidDynamicKey: typeof foo = dynamic; +>invalidDynamicKey : RegisteredSymbol<"foo"> +>foo : RegisteredSymbol<"foo"> +>dynamic : symbol + +declare const unionKey: "foo" | "bar"; +>unionKey : "bar" | "foo" + +let registeredUnion: RegisteredSymbol<"foo" | "bar"> = Symbol.for(unionKey); +>registeredUnion : RegisteredSymbol<"bar"> | RegisteredSymbol<"foo"> +>Symbol.for(unionKey) : RegisteredSymbol<"bar"> | RegisteredSymbol<"foo"> +>Symbol.for : (key: Key) => RegisteredSymbol +>Symbol : SymbolConstructor +>for : (key: Key) => RegisteredSymbol +>unionKey : "bar" | "foo" + +let invalidUnionKey: typeof foo = registeredUnion; +>invalidUnionKey : RegisteredSymbol<"foo"> +>foo : RegisteredSymbol<"foo"> +>registeredUnion : RegisteredSymbol<"bar"> | RegisteredSymbol<"foo"> + interface WithRegisteredKeys { [foo]: string; >[foo] : string diff --git a/tsc/testdata/tests/cases/compiler/registeredSymbolIntrinsic.ts b/tsc/testdata/tests/cases/compiler/registeredSymbolIntrinsic.ts index d245ad80a7e20..9fbe92c83951d 100644 --- a/tsc/testdata/tests/cases/compiler/registeredSymbolIntrinsic.ts +++ b/tsc/testdata/tests/cases/compiler/registeredSymbolIntrinsic.ts @@ -12,6 +12,12 @@ let widenedSymbol: symbol = foo; declare const key: string; let registeredString: RegisteredSymbol = Symbol.for(key); +let dynamic = Symbol.for(key); +let invalidDynamicKey: typeof foo = dynamic; + +declare const unionKey: "foo" | "bar"; +let registeredUnion: RegisteredSymbol<"foo" | "bar"> = Symbol.for(unionKey); +let invalidUnionKey: typeof foo = registeredUnion; interface WithRegisteredKeys { [foo]: string; From c6d0ad8471761b0a5bcede299d445ba15d7877ef Mon Sep 17 00:00:00 2001 From: Michael FIG Date: Sat, 26 Sep 2026 10:41:01 -0600 Subject: [PATCH 6/6] Represent deferred registered symbols with a distinct type flag Avoid assigning a unique symbol identity to Symbol.for calls with unresolved keys. Add a regression case for indexed access through two generic registry keys. Co-authored-by: Codex --- .../typescript/src/enums/typeFlags.enum.ts | 8 +- packages/typescript/src/enums/typeFlags.ts | 20 ++--- tsc/internal/api/enum_values_generated.go | 2 +- tsc/internal/checker/checker.go | 22 +++-- tsc/internal/checker/relater.go | 2 + tsc/internal/checker/types.go | 87 +++++++++++-------- tsc/internal/checker/utilities.go | 4 + .../registeredSymbolDeferredKey.errors.txt | 28 ++++++ .../compiler/registeredSymbolDeferredKey.js | 30 +++++++ .../registeredSymbolDeferredKey.symbols | 75 ++++++++++++++++ .../registeredSymbolDeferredKey.types | 80 +++++++++++++++++ .../compiler/registeredSymbolDeferredKey.ts | 25 ++++++ 12 files changed, 323 insertions(+), 60 deletions(-) create mode 100644 tsc/testdata/baselines/reference/compiler/registeredSymbolDeferredKey.errors.txt create mode 100644 tsc/testdata/baselines/reference/compiler/registeredSymbolDeferredKey.js create mode 100644 tsc/testdata/baselines/reference/compiler/registeredSymbolDeferredKey.symbols create mode 100644 tsc/testdata/baselines/reference/compiler/registeredSymbolDeferredKey.types create mode 100644 tsc/testdata/tests/cases/compiler/registeredSymbolDeferredKey.ts diff --git a/packages/typescript/src/enums/typeFlags.enum.ts b/packages/typescript/src/enums/typeFlags.enum.ts index 282cbcfe49406..490a8811f7033 100644 --- a/packages/typescript/src/enums/typeFlags.enum.ts +++ b/packages/typescript/src/enums/typeFlags.enum.ts @@ -33,7 +33,7 @@ export enum TypeFlags { Intersection = 1 << 28, Reserved1 = 1 << 29, Reserved2 = 1 << 30, - Reserved3 = 1 << 31, + RegisteredESSymbol = 1 << 31, AnyOrUnknown = Any | Unknown, Nullable = Undefined | Null, Literal = StringLiteral | NumberLiteral | BigIntLiteral | BooleanLiteral, @@ -49,7 +49,7 @@ export enum TypeFlags { BigIntLike = BigInt | BigIntLiteral, BooleanLike = Boolean | BooleanLiteral, EnumLike = Enum | EnumLiteral, - ESSymbolLike = ESSymbol | UniqueESSymbol, + ESSymbolLike = ESSymbol | UniqueESSymbol | RegisteredESSymbol, VoidLike = Void | Undefined, Primitive = StringLike | NumberLike | BigIntLike | BooleanLike | EnumLike | ESSymbolLike | VoidLike | Null, DefinitelyNonNullable = StringLike | NumberLike | BigIntLike | BooleanLike | EnumLike | ESSymbolLike | Object | NonPrimitive, @@ -58,14 +58,14 @@ export enum TypeFlags { StructuredType = Object | Union | Intersection, TypeVariable = TypeParameter | IndexedAccess, InstantiableNonPrimitive = TypeVariable | Conditional | Substitution, - InstantiablePrimitive = Index | TemplateLiteral | StringMapping, + InstantiablePrimitive = Index | TemplateLiteral | StringMapping | RegisteredESSymbol, Instantiable = InstantiableNonPrimitive | InstantiablePrimitive, StructuredOrInstantiable = StructuredType | Instantiable, ObjectFlagsType = Any | Nullable | Never | Object | Union | Intersection, Simplifiable = IndexedAccess | Conditional | Index, Singleton = Any | Unknown | String | Number | Boolean | BigInt | ESSymbol | Void | Undefined | Null | Never | NonPrimitive, Narrowable = Any | Unknown | StructuredOrInstantiable | StringLike | NumberLike | BigIntLike | BooleanLike | ESSymbol | UniqueESSymbol | NonPrimitive, - IncludesMask = Any | Unknown | Primitive | Never | Object | Union | Intersection | NonPrimitive | TemplateLiteral | StringMapping, + IncludesMask = Any | Unknown | Primitive | Never | Object | Union | Intersection | NonPrimitive | TemplateLiteral | StringMapping | RegisteredESSymbol, IncludesMissingType = TypeParameter, IncludesNonWideningType = Index, IncludesWildcard = IndexedAccess, diff --git a/packages/typescript/src/enums/typeFlags.ts b/packages/typescript/src/enums/typeFlags.ts index e1e8432972020..cb68e6e3f5527 100644 --- a/packages/typescript/src/enums/typeFlags.ts +++ b/packages/typescript/src/enums/typeFlags.ts @@ -33,7 +33,7 @@ export var TypeFlags: any; TypeFlags[TypeFlags["Intersection"] = 268435456] = "Intersection"; TypeFlags[TypeFlags["Reserved1"] = 536870912] = "Reserved1"; TypeFlags[TypeFlags["Reserved2"] = 1073741824] = "Reserved2"; - TypeFlags[TypeFlags["Reserved3"] = -2147483648] = "Reserved3"; + TypeFlags[TypeFlags["RegisteredESSymbol"] = -2147483648] = "RegisteredESSymbol"; TypeFlags[TypeFlags["AnyOrUnknown"] = 3] = "AnyOrUnknown"; TypeFlags[TypeFlags["Nullable"] = 12] = "Nullable"; TypeFlags[TypeFlags["Literal"] = 15360] = "Literal"; @@ -49,23 +49,23 @@ export var TypeFlags: any; TypeFlags[TypeFlags["BigIntLike"] = 4224] = "BigIntLike"; TypeFlags[TypeFlags["BooleanLike"] = 8448] = "BooleanLike"; TypeFlags[TypeFlags["EnumLike"] = 98304] = "EnumLike"; - TypeFlags[TypeFlags["ESSymbolLike"] = 16896] = "ESSymbolLike"; + TypeFlags[TypeFlags["ESSymbolLike"] = -2147466752] = "ESSymbolLike"; TypeFlags[TypeFlags["VoidLike"] = 20] = "VoidLike"; - TypeFlags[TypeFlags["Primitive"] = 12713980] = "Primitive"; - TypeFlags[TypeFlags["DefinitelyNonNullable"] = 13893600] = "DefinitelyNonNullable"; - TypeFlags[TypeFlags["DisjointDomains"] = 12812284] = "DisjointDomains"; + TypeFlags[TypeFlags["Primitive"] = -2134769668] = "Primitive"; + TypeFlags[TypeFlags["DefinitelyNonNullable"] = -2133590048] = "DefinitelyNonNullable"; + TypeFlags[TypeFlags["DisjointDomains"] = -2134671364] = "DisjointDomains"; TypeFlags[TypeFlags["UnionOrIntersection"] = 402653184] = "UnionOrIntersection"; TypeFlags[TypeFlags["StructuredType"] = 403701760] = "StructuredType"; TypeFlags[TypeFlags["TypeVariable"] = 34078720] = "TypeVariable"; TypeFlags[TypeFlags["InstantiableNonPrimitive"] = 117964800] = "InstantiableNonPrimitive"; - TypeFlags[TypeFlags["InstantiablePrimitive"] = 14680064] = "InstantiablePrimitive"; - TypeFlags[TypeFlags["Instantiable"] = 132644864] = "Instantiable"; - TypeFlags[TypeFlags["StructuredOrInstantiable"] = 536346624] = "StructuredOrInstantiable"; + TypeFlags[TypeFlags["InstantiablePrimitive"] = -2132803584] = "InstantiablePrimitive"; + TypeFlags[TypeFlags["Instantiable"] = -2014838784] = "Instantiable"; + TypeFlags[TypeFlags["StructuredOrInstantiable"] = -1611137024] = "StructuredOrInstantiable"; TypeFlags[TypeFlags["ObjectFlagsType"] = 403963917] = "ObjectFlagsType"; TypeFlags[TypeFlags["Simplifiable"] = 102760448] = "Simplifiable"; TypeFlags[TypeFlags["Singleton"] = 394239] = "Singleton"; - TypeFlags[TypeFlags["Narrowable"] = 536575971] = "Narrowable"; - TypeFlags[TypeFlags["IncludesMask"] = 416808959] = "IncludesMask"; + TypeFlags[TypeFlags["Narrowable"] = -1610907677] = "Narrowable"; + TypeFlags[TypeFlags["IncludesMask"] = -1730674689] = "IncludesMask"; TypeFlags[TypeFlags["IncludesMissingType"] = 524288] = "IncludesMissingType"; TypeFlags[TypeFlags["IncludesNonWideningType"] = 2097152] = "IncludesNonWideningType"; TypeFlags[TypeFlags["IncludesWildcard"] = 33554432] = "IncludesWildcard"; diff --git a/tsc/internal/api/enum_values_generated.go b/tsc/internal/api/enum_values_generated.go index d1f15a1830af3..0739c44a2d0d9 100644 --- a/tsc/internal/api/enum_values_generated.go +++ b/tsc/internal/api/enum_values_generated.go @@ -159,7 +159,7 @@ func main() { "Intersection": toInt32(checker.TypeFlagsIntersection), "Reserved1": toInt32(checker.TypeFlagsReserved1), "Reserved2": toInt32(checker.TypeFlagsReserved2), - "Reserved3": toInt32(checker.TypeFlagsReserved3), + "RegisteredESSymbol": toInt32(checker.TypeFlagsRegisteredESSymbol), "AnyOrUnknown": toInt32(checker.TypeFlagsAnyOrUnknown), "Nullable": toInt32(checker.TypeFlagsNullable), "Literal": toInt32(checker.TypeFlagsLiteral), diff --git a/tsc/internal/checker/checker.go b/tsc/internal/checker/checker.go index e952983ccbcb4..a4f11beb04623 100644 --- a/tsc/internal/checker/checker.go +++ b/tsc/internal/checker/checker.go @@ -22637,7 +22637,7 @@ func (c *Checker) instantiateTypeWorker(t *Type, m *TypeMapper, alias *TypeAlias return c.getTemplateLiteralType(t.AsTemplateLiteralType().texts, c.instantiateTypes(t.AsTemplateLiteralType().types, m)) case flags&TypeFlagsStringMapping != 0: return c.getStringMappingType(t.symbol, c.instantiateType(t.AsStringMappingType().target, m)) - case flags&TypeFlagsUniqueESSymbol != 0 && isRegisteredSymbolAlias(t.alias): + case flags&TypeFlagsRegisteredESSymbol != 0: newAlias := c.instantiateTypeAlias(t.alias, m) return c.getRegisteredESSymbolType(newAlias.typeArguments[0], newAlias) case flags&TypeFlagsConditional != 0: @@ -23374,6 +23374,9 @@ func (c *Checker) getESSymbolLikeTypeForNode(node *ast.Node) *Type { } func (c *Checker) getRegisteredESSymbolType(keyType *Type, alias *TypeAlias) *Type { + if keyType.flags&TypeFlagsNever != 0 { + return c.neverType + } if keyType.flags&TypeFlagsUnion != 0 { members := make([]*Type, 0, len(keyType.Types())) for _, member := range keyType.Types() { @@ -23385,17 +23388,20 @@ func (c *Checker) getRegisteredESSymbolType(keyType *Type, alias *TypeAlias) *Ty } return c.getUnionType(members) } - // Keep a type parameter deferred so instantiating Symbol.for's generic - // return type can resolve the actual key supplied at the call site. if keyType.flags&(TypeFlagsStringOrNumberLiteral|TypeFlagsTypeParameter) == 0 { return c.esSymbolType } key := c.getRegisteredESSymbolTypeKey(keyType) t := c.registeredESSymbolTypes[key] if t == nil { - name := ast.InternalSymbolNamePrefix + "@@" + c.getRegisteredESSymbolNameText(keyType) - symbol := c.newSymbol(ast.SymbolFlagsProperty, name) - t = c.newUniqueESSymbolType(symbol, name) + if keyType.flags&TypeFlagsTypeParameter != 0 { + data := &RegisteredESSymbolType{target: keyType} + t = c.newType(TypeFlagsRegisteredESSymbol, ObjectFlagsNone, data) + } else { + name := ast.InternalSymbolNamePrefix + "@@" + c.getRegisteredESSymbolNameText(keyType) + symbol := c.newSymbol(ast.SymbolFlagsProperty, name) + t = c.newUniqueESSymbolType(symbol, name) + } c.registeredESSymbolTypes[key] = t } t.alias = alias @@ -27913,7 +27919,7 @@ func (c *Checker) getBaseConstraintOrType(t *Type) *Type { } func (c *Checker) getBaseConstraintOfType(t *Type) *Type { - if t.flags&(TypeFlagsInstantiableNonPrimitive|TypeFlagsUnionOrIntersection|TypeFlagsTemplateLiteral|TypeFlagsStringMapping|TypeFlagsIndex) != 0 || c.isGenericTupleType(t) { + if t.flags&(TypeFlagsInstantiableNonPrimitive|TypeFlagsUnionOrIntersection|TypeFlagsTemplateLiteral|TypeFlagsStringMapping|TypeFlagsRegisteredESSymbol|TypeFlagsIndex) != 0 || c.isGenericTupleType(t) { constraint := c.getResolvedBaseConstraint(t, nil) if constraint != c.noConstraintType && constraint != c.circularConstraintType { return constraint @@ -28026,6 +28032,8 @@ func (c *Checker) computeBaseConstraint(t *Type, stack []RecursionId) *Type { return c.getStringMappingType(t.symbol, constraint) } return c.stringType + case t.flags&TypeFlagsRegisteredESSymbol != 0: + return c.esSymbolType case t.flags&TypeFlagsIndexedAccess != 0: if c.isMappedTypeGenericIndexedAccess(t) { // For indexed access types of the form { [P in K]: E }[X], where K is non-generic and X is generic, diff --git a/tsc/internal/checker/relater.go b/tsc/internal/checker/relater.go index 9d71d2504ca0c..430f0c02a5c70 100644 --- a/tsc/internal/checker/relater.go +++ b/tsc/internal/checker/relater.go @@ -3397,6 +3397,8 @@ func (r *Relater) structuredTypeRelatedToWorker(source *Type, target *Type, repo if source.AsStringMappingType().Symbol() == target.AsStringMappingType().Symbol() { return r.isRelatedTo(source.AsStringMappingType().target, target.AsStringMappingType().target, RecursionFlagsBoth, false /*reportErrors*/) } + case source.flags&TypeFlagsRegisteredESSymbol != 0: + return r.isRelatedTo(source.AsRegisteredESSymbolType().target, target.AsRegisteredESSymbolType().target, RecursionFlagsBoth, false /*reportErrors*/) } if source.flags&TypeFlagsObject == 0 { return TernaryFalse diff --git a/tsc/internal/checker/types.go b/tsc/internal/checker/types.go index f5a8a37954c85..157394867f63a 100644 --- a/tsc/internal/checker/types.go +++ b/tsc/internal/checker/types.go @@ -437,39 +437,39 @@ type TypeFlags uint32 // conditional types should sort last as those types are potentially recursive and possibly infinite. const ( - TypeFlagsNone TypeFlags = 0 - TypeFlagsAny TypeFlags = 1 << 0 - TypeFlagsUnknown TypeFlags = 1 << 1 - TypeFlagsUndefined TypeFlags = 1 << 2 - TypeFlagsNull TypeFlags = 1 << 3 - TypeFlagsVoid TypeFlags = 1 << 4 - TypeFlagsString TypeFlags = 1 << 5 - TypeFlagsNumber TypeFlags = 1 << 6 - TypeFlagsBigInt TypeFlags = 1 << 7 - TypeFlagsBoolean TypeFlags = 1 << 8 - TypeFlagsESSymbol TypeFlags = 1 << 9 // Type of symbol primitive introduced in ES6 - TypeFlagsStringLiteral TypeFlags = 1 << 10 - TypeFlagsNumberLiteral TypeFlags = 1 << 11 - TypeFlagsBigIntLiteral TypeFlags = 1 << 12 - TypeFlagsBooleanLiteral TypeFlags = 1 << 13 - TypeFlagsUniqueESSymbol TypeFlags = 1 << 14 // unique symbol - TypeFlagsEnumLiteral TypeFlags = 1 << 15 // Always combined with StringLiteral, NumberLiteral, or Union - TypeFlagsEnum TypeFlags = 1 << 16 // Numeric computed enum member value (must be right after EnumLiteral, see getSortOrderFlags) - TypeFlagsNonPrimitive TypeFlags = 1 << 17 // intrinsic object type - TypeFlagsNever TypeFlags = 1 << 18 // Never type - TypeFlagsTypeParameter TypeFlags = 1 << 19 // Type parameter - TypeFlagsObject TypeFlags = 1 << 20 // Object type - TypeFlagsIndex TypeFlags = 1 << 21 // keyof T - TypeFlagsTemplateLiteral TypeFlags = 1 << 22 // Template literal type - TypeFlagsStringMapping TypeFlags = 1 << 23 // Uppercase/Lowercase type - TypeFlagsSubstitution TypeFlags = 1 << 24 // Type parameter substitution - TypeFlagsIndexedAccess TypeFlags = 1 << 25 // T[K] - TypeFlagsConditional TypeFlags = 1 << 26 // T extends U ? X : Y - TypeFlagsUnion TypeFlags = 1 << 27 // Union (T | U) - TypeFlagsIntersection TypeFlags = 1 << 28 // Intersection (T & U) - TypeFlagsReserved1 TypeFlags = 1 << 29 // Used by union/intersection type construction - TypeFlagsReserved2 TypeFlags = 1 << 30 // Used by union/intersection type construction - TypeFlagsReserved3 TypeFlags = 1 << 31 + TypeFlagsNone TypeFlags = 0 + TypeFlagsAny TypeFlags = 1 << 0 + TypeFlagsUnknown TypeFlags = 1 << 1 + TypeFlagsUndefined TypeFlags = 1 << 2 + TypeFlagsNull TypeFlags = 1 << 3 + TypeFlagsVoid TypeFlags = 1 << 4 + TypeFlagsString TypeFlags = 1 << 5 + TypeFlagsNumber TypeFlags = 1 << 6 + TypeFlagsBigInt TypeFlags = 1 << 7 + TypeFlagsBoolean TypeFlags = 1 << 8 + TypeFlagsESSymbol TypeFlags = 1 << 9 // Type of symbol primitive introduced in ES6 + TypeFlagsStringLiteral TypeFlags = 1 << 10 + TypeFlagsNumberLiteral TypeFlags = 1 << 11 + TypeFlagsBigIntLiteral TypeFlags = 1 << 12 + TypeFlagsBooleanLiteral TypeFlags = 1 << 13 + TypeFlagsUniqueESSymbol TypeFlags = 1 << 14 // unique symbol + TypeFlagsEnumLiteral TypeFlags = 1 << 15 // Always combined with StringLiteral, NumberLiteral, or Union + TypeFlagsEnum TypeFlags = 1 << 16 // Numeric computed enum member value (must be right after EnumLiteral, see getSortOrderFlags) + TypeFlagsNonPrimitive TypeFlags = 1 << 17 // intrinsic object type + TypeFlagsNever TypeFlags = 1 << 18 // Never type + TypeFlagsTypeParameter TypeFlags = 1 << 19 // Type parameter + TypeFlagsObject TypeFlags = 1 << 20 // Object type + TypeFlagsIndex TypeFlags = 1 << 21 // keyof T + TypeFlagsTemplateLiteral TypeFlags = 1 << 22 // Template literal type + TypeFlagsStringMapping TypeFlags = 1 << 23 // Uppercase/Lowercase type + TypeFlagsSubstitution TypeFlags = 1 << 24 // Type parameter substitution + TypeFlagsIndexedAccess TypeFlags = 1 << 25 // T[K] + TypeFlagsConditional TypeFlags = 1 << 26 // T extends U ? X : Y + TypeFlagsUnion TypeFlags = 1 << 27 // Union (T | U) + TypeFlagsIntersection TypeFlags = 1 << 28 // Intersection (T & U) + TypeFlagsReserved1 TypeFlags = 1 << 29 // Used by union/intersection type construction + TypeFlagsReserved2 TypeFlags = 1 << 30 // Used by union/intersection type construction + TypeFlagsRegisteredESSymbol TypeFlags = 1 << 31 // RegisteredSymbol with an unresolved key TypeFlagsAnyOrUnknown = TypeFlagsAny | TypeFlagsUnknown TypeFlagsNullable = TypeFlagsUndefined | TypeFlagsNull @@ -486,7 +486,7 @@ const ( TypeFlagsBigIntLike = TypeFlagsBigInt | TypeFlagsBigIntLiteral TypeFlagsBooleanLike = TypeFlagsBoolean | TypeFlagsBooleanLiteral TypeFlagsEnumLike = TypeFlagsEnum | TypeFlagsEnumLiteral - TypeFlagsESSymbolLike = TypeFlagsESSymbol | TypeFlagsUniqueESSymbol + TypeFlagsESSymbolLike = TypeFlagsESSymbol | TypeFlagsUniqueESSymbol | TypeFlagsRegisteredESSymbol TypeFlagsVoidLike = TypeFlagsVoid | TypeFlagsUndefined TypeFlagsPrimitive = TypeFlagsStringLike | TypeFlagsNumberLike | TypeFlagsBigIntLike | TypeFlagsBooleanLike | TypeFlagsEnumLike | TypeFlagsESSymbolLike | TypeFlagsVoidLike | TypeFlagsNull TypeFlagsDefinitelyNonNullable = TypeFlagsStringLike | TypeFlagsNumberLike | TypeFlagsBigIntLike | TypeFlagsBooleanLike | TypeFlagsEnumLike | TypeFlagsESSymbolLike | TypeFlagsObject | TypeFlagsNonPrimitive @@ -495,7 +495,7 @@ const ( TypeFlagsStructuredType = TypeFlagsObject | TypeFlagsUnion | TypeFlagsIntersection TypeFlagsTypeVariable = TypeFlagsTypeParameter | TypeFlagsIndexedAccess TypeFlagsInstantiableNonPrimitive = TypeFlagsTypeVariable | TypeFlagsConditional | TypeFlagsSubstitution - TypeFlagsInstantiablePrimitive = TypeFlagsIndex | TypeFlagsTemplateLiteral | TypeFlagsStringMapping + TypeFlagsInstantiablePrimitive = TypeFlagsIndex | TypeFlagsTemplateLiteral | TypeFlagsStringMapping | TypeFlagsRegisteredESSymbol TypeFlagsInstantiable = TypeFlagsInstantiableNonPrimitive | TypeFlagsInstantiablePrimitive TypeFlagsStructuredOrInstantiable = TypeFlagsStructuredType | TypeFlagsInstantiable TypeFlagsObjectFlagsType = TypeFlagsAny | TypeFlagsNullable | TypeFlagsNever | TypeFlagsObject | TypeFlagsUnion | TypeFlagsIntersection @@ -505,7 +505,7 @@ const ( // This *should* be every type other than null, undefined, void, and never TypeFlagsNarrowable = TypeFlagsAny | TypeFlagsUnknown | TypeFlagsStructuredOrInstantiable | TypeFlagsStringLike | TypeFlagsNumberLike | TypeFlagsBigIntLike | TypeFlagsBooleanLike | TypeFlagsESSymbol | TypeFlagsUniqueESSymbol | TypeFlagsNonPrimitive // The following flags are aggregated during union and intersection type construction - TypeFlagsIncludesMask = TypeFlagsAny | TypeFlagsUnknown | TypeFlagsPrimitive | TypeFlagsNever | TypeFlagsObject | TypeFlagsUnion | TypeFlagsIntersection | TypeFlagsNonPrimitive | TypeFlagsTemplateLiteral | TypeFlagsStringMapping + TypeFlagsIncludesMask = TypeFlagsAny | TypeFlagsUnknown | TypeFlagsPrimitive | TypeFlagsNever | TypeFlagsObject | TypeFlagsUnion | TypeFlagsIntersection | TypeFlagsNonPrimitive | TypeFlagsTemplateLiteral | TypeFlagsStringMapping | TypeFlagsRegisteredESSymbol // The following flags are used for different purposes during union and intersection type construction TypeFlagsIncludesMissingType = TypeFlagsTypeParameter TypeFlagsIncludesNonWideningType = TypeFlagsIndex @@ -545,6 +545,7 @@ var typeFlagNames = [...]struct { {TypeFlagsIndex, "Index"}, {TypeFlagsTemplateLiteral, "TemplateLiteral"}, {TypeFlagsStringMapping, "StringMapping"}, + {TypeFlagsRegisteredESSymbol, "RegisteredESSymbol"}, {TypeFlagsSubstitution, "Substitution"}, {TypeFlagsIndexedAccess, "IndexedAccess"}, {TypeFlagsConditional, "Conditional"}, @@ -724,8 +725,11 @@ func (t *Type) AsIndexType() *IndexType { return t.data.(*In func (t *Type) AsIndexedAccessType() *IndexedAccessType { return t.data.(*IndexedAccessType) } func (t *Type) AsTemplateLiteralType() *TemplateLiteralType { return t.data.(*TemplateLiteralType) } func (t *Type) AsStringMappingType() *StringMappingType { return t.data.(*StringMappingType) } -func (t *Type) AsSubstitutionType() *SubstitutionType { return t.data.(*SubstitutionType) } -func (t *Type) AsConditionalType() *ConditionalType { return t.data.(*ConditionalType) } +func (t *Type) AsRegisteredESSymbolType() *RegisteredESSymbolType { + return t.data.(*RegisteredESSymbolType) +} +func (t *Type) AsSubstitutionType() *SubstitutionType { return t.data.(*SubstitutionType) } +func (t *Type) AsConditionalType() *ConditionalType { return t.data.(*ConditionalType) } // Casts for embedded struct types @@ -760,6 +764,8 @@ func (t *Type) Target() *Type { return t.AsIndexType().target case t.flags&TypeFlagsStringMapping != 0: return t.AsStringMappingType().target + case t.flags&TypeFlagsRegisteredESSymbol != 0: + return t.AsRegisteredESSymbolType().target case t.flags&TypeFlagsObject != 0 && t.objectFlags&ObjectFlagsMapped != 0: return t.AsMappedType().target } @@ -1247,6 +1253,11 @@ type StringMappingType struct { func (t *StringMappingType) Target() *Type { return t.target } +type RegisteredESSymbolType struct { + ConstrainedType + target *Type +} + type SubstitutionType struct { ConstrainedType baseType *Type // Target type diff --git a/tsc/internal/checker/utilities.go b/tsc/internal/checker/utilities.go index 0a68372fcef3c..acd04cd7bf54b 100644 --- a/tsc/internal/checker/utilities.go +++ b/tsc/internal/checker/utilities.go @@ -616,6 +616,10 @@ func CompareTypes(t1, t2 *Type) int { if c := CompareTypes(t1.AsStringMappingType().target, t2.AsStringMappingType().target); c != 0 { return c } + case t1.flags&TypeFlagsRegisteredESSymbol != 0: + if c := CompareTypes(t1.AsRegisteredESSymbolType().target, t2.AsRegisteredESSymbolType().target); c != 0 { + return c + } } // Fall back to type IDs. This results in type creation order for built-in types. return int(t1.id) - int(t2.id) diff --git a/tsc/testdata/baselines/reference/compiler/registeredSymbolDeferredKey.errors.txt b/tsc/testdata/baselines/reference/compiler/registeredSymbolDeferredKey.errors.txt new file mode 100644 index 0000000000000..69deb62582dc4 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/registeredSymbolDeferredKey.errors.txt @@ -0,0 +1,28 @@ +registeredSymbolDeferredKey.ts(15,11): error TS2322: Type '"first" | undefined' is not assignable to type '"first"'. + Type 'undefined' is not assignable to type '"first"'. + + +==== registeredSymbolDeferredKey.ts (1 errors) ==== + export function make(key: K) { + const registered = Symbol.for(key); + const widened: symbol = registered; + return registered; + } + + export function unreachable(key: never): never { + return Symbol.for(key); + } + + export function read(first: K, second: K) { + const firstKey = Symbol.for(first); + const record = { [firstKey]: "first" } as const; + const secondKey = Symbol.for(second); + const value: "first" = record[secondKey]; + ~~~~~ +!!! error TS2322: Type '"first" | undefined' is not assignable to type '"first"'. +!!! error TS2322: Type 'undefined' is not assignable to type '"first"'. + return value; + } + + read<"a" | "b">("a", "b"); + \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/compiler/registeredSymbolDeferredKey.js b/tsc/testdata/baselines/reference/compiler/registeredSymbolDeferredKey.js new file mode 100644 index 0000000000000..9f7cb0438d3a8 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/registeredSymbolDeferredKey.js @@ -0,0 +1,30 @@ +//// [tests/cases/compiler/registeredSymbolDeferredKey.ts] //// + +//// [registeredSymbolDeferredKey.ts] +export function make(key: K) { + const registered = Symbol.for(key); + const widened: symbol = registered; + return registered; +} + +export function unreachable(key: never): never { + return Symbol.for(key); +} + +export function read(first: K, second: K) { + const firstKey = Symbol.for(first); + const record = { [firstKey]: "first" } as const; + const secondKey = Symbol.for(second); + const value: "first" = record[secondKey]; + return value; +} + +read<"a" | "b">("a", "b"); + + + + +//// [registeredSymbolDeferredKey.d.ts] +export declare function make(key: K): RegisteredSymbol; +export declare function unreachable(key: never): never; +export declare function read(first: K, second: K): "first"; diff --git a/tsc/testdata/baselines/reference/compiler/registeredSymbolDeferredKey.symbols b/tsc/testdata/baselines/reference/compiler/registeredSymbolDeferredKey.symbols new file mode 100644 index 0000000000000..064eb83aba8e3 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/registeredSymbolDeferredKey.symbols @@ -0,0 +1,75 @@ +//// [tests/cases/compiler/registeredSymbolDeferredKey.ts] //// + +=== registeredSymbolDeferredKey.ts === +export function make(key: K) { +>make : Symbol(make, Decl(registeredSymbolDeferredKey.ts, 0, 0)) +>K : Symbol(K, Decl(registeredSymbolDeferredKey.ts, 0, 21)) +>key : Symbol(key, Decl(registeredSymbolDeferredKey.ts, 0, 39)) +>K : Symbol(K, Decl(registeredSymbolDeferredKey.ts, 0, 21)) + + const registered = Symbol.for(key); +>registered : Symbol(registered, Decl(registeredSymbolDeferredKey.ts, 1, 9)) +>Symbol.for : Symbol(SymbolConstructor.for, Decl(lib.es2015.symbol.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>for : Symbol(SymbolConstructor.for, Decl(lib.es2015.symbol.d.ts, --, --)) +>key : Symbol(key, Decl(registeredSymbolDeferredKey.ts, 0, 39)) + + const widened: symbol = registered; +>widened : Symbol(widened, Decl(registeredSymbolDeferredKey.ts, 2, 9)) +>registered : Symbol(registered, Decl(registeredSymbolDeferredKey.ts, 1, 9)) + + return registered; +>registered : Symbol(registered, Decl(registeredSymbolDeferredKey.ts, 1, 9)) +} + +export function unreachable(key: never): never { +>unreachable : Symbol(unreachable, Decl(registeredSymbolDeferredKey.ts, 4, 1)) +>key : Symbol(key, Decl(registeredSymbolDeferredKey.ts, 6, 28)) + + return Symbol.for(key); +>Symbol.for : Symbol(SymbolConstructor.for, Decl(lib.es2015.symbol.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>for : Symbol(SymbolConstructor.for, Decl(lib.es2015.symbol.d.ts, --, --)) +>key : Symbol(key, Decl(registeredSymbolDeferredKey.ts, 6, 28)) +} + +export function read(first: K, second: K) { +>read : Symbol(read, Decl(registeredSymbolDeferredKey.ts, 8, 1)) +>K : Symbol(K, Decl(registeredSymbolDeferredKey.ts, 10, 21)) +>first : Symbol(first, Decl(registeredSymbolDeferredKey.ts, 10, 39)) +>K : Symbol(K, Decl(registeredSymbolDeferredKey.ts, 10, 21)) +>second : Symbol(second, Decl(registeredSymbolDeferredKey.ts, 10, 48)) +>K : Symbol(K, Decl(registeredSymbolDeferredKey.ts, 10, 21)) + + const firstKey = Symbol.for(first); +>firstKey : Symbol(firstKey, Decl(registeredSymbolDeferredKey.ts, 11, 9)) +>Symbol.for : Symbol(SymbolConstructor.for, Decl(lib.es2015.symbol.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>for : Symbol(SymbolConstructor.for, Decl(lib.es2015.symbol.d.ts, --, --)) +>first : Symbol(first, Decl(registeredSymbolDeferredKey.ts, 10, 39)) + + const record = { [firstKey]: "first" } as const; +>record : Symbol(record, Decl(registeredSymbolDeferredKey.ts, 12, 9)) +>[firstKey] : Symbol([firstKey], Decl(registeredSymbolDeferredKey.ts, 12, 20)) +>firstKey : Symbol(firstKey, Decl(registeredSymbolDeferredKey.ts, 11, 9)) +>const : Symbol(const) + + const secondKey = Symbol.for(second); +>secondKey : Symbol(secondKey, Decl(registeredSymbolDeferredKey.ts, 13, 9)) +>Symbol.for : Symbol(SymbolConstructor.for, Decl(lib.es2015.symbol.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>for : Symbol(SymbolConstructor.for, Decl(lib.es2015.symbol.d.ts, --, --)) +>second : Symbol(second, Decl(registeredSymbolDeferredKey.ts, 10, 48)) + + const value: "first" = record[secondKey]; +>value : Symbol(value, Decl(registeredSymbolDeferredKey.ts, 14, 9)) +>record : Symbol(record, Decl(registeredSymbolDeferredKey.ts, 12, 9)) +>secondKey : Symbol(secondKey, Decl(registeredSymbolDeferredKey.ts, 13, 9)) + + return value; +>value : Symbol(value, Decl(registeredSymbolDeferredKey.ts, 14, 9)) +} + +read<"a" | "b">("a", "b"); +>read : Symbol(read, Decl(registeredSymbolDeferredKey.ts, 8, 1)) + diff --git a/tsc/testdata/baselines/reference/compiler/registeredSymbolDeferredKey.types b/tsc/testdata/baselines/reference/compiler/registeredSymbolDeferredKey.types new file mode 100644 index 0000000000000..f0641e90cbe8a --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/registeredSymbolDeferredKey.types @@ -0,0 +1,80 @@ +//// [tests/cases/compiler/registeredSymbolDeferredKey.ts] //// + +=== registeredSymbolDeferredKey.ts === +export function make(key: K) { +>make : (key: K) => RegisteredSymbol +>key : K + + const registered = Symbol.for(key); +>registered : RegisteredSymbol +>Symbol.for(key) : RegisteredSymbol +>Symbol.for : (key: Key) => RegisteredSymbol +>Symbol : SymbolConstructor +>for : (key: Key) => RegisteredSymbol +>key : K + + const widened: symbol = registered; +>widened : symbol +>registered : RegisteredSymbol + + return registered; +>registered : RegisteredSymbol +} + +export function unreachable(key: never): never { +>unreachable : (key: never) => never +>key : never + + return Symbol.for(key); +>Symbol.for(key) : never +>Symbol.for : (key: Key) => RegisteredSymbol +>Symbol : SymbolConstructor +>for : (key: Key) => RegisteredSymbol +>key : never +} + +export function read(first: K, second: K) { +>read : (first: K, second: K) => "first" +>first : K +>second : K + + const firstKey = Symbol.for(first); +>firstKey : RegisteredSymbol +>Symbol.for(first) : RegisteredSymbol +>Symbol.for : (key: Key) => RegisteredSymbol +>Symbol : SymbolConstructor +>for : (key: Key) => RegisteredSymbol +>first : K + + const record = { [firstKey]: "first" } as const; +>record : { readonly [x: symbol]: "first"; } +>{ [firstKey]: "first" } as const : { readonly [x: symbol]: "first"; } +>{ [firstKey]: "first" } : { readonly [x: symbol]: "first"; } +>[firstKey] : "first" +>firstKey : RegisteredSymbol +>"first" : "first" + + const secondKey = Symbol.for(second); +>secondKey : RegisteredSymbol +>Symbol.for(second) : RegisteredSymbol +>Symbol.for : (key: Key) => RegisteredSymbol +>Symbol : SymbolConstructor +>for : (key: Key) => RegisteredSymbol +>second : K + + const value: "first" = record[secondKey]; +>value : "first" +>record[secondKey] : "first" | undefined +>record : { readonly [x: symbol]: "first"; } +>secondKey : RegisteredSymbol + + return value; +>value : "first" +} + +read<"a" | "b">("a", "b"); +>read<"a" | "b">("a", "b") : "first" +>read : (first: K, second: K) => "first" +>"a" : "a" +>"b" : "b" + diff --git a/tsc/testdata/tests/cases/compiler/registeredSymbolDeferredKey.ts b/tsc/testdata/tests/cases/compiler/registeredSymbolDeferredKey.ts new file mode 100644 index 0000000000000..c2f092d62adeb --- /dev/null +++ b/tsc/testdata/tests/cases/compiler/registeredSymbolDeferredKey.ts @@ -0,0 +1,25 @@ +// @target: es2015 +// @strict: true +// @noUncheckedIndexedAccess: true +// @declaration: true +// @emitDeclarationOnly: true + +export function make(key: K) { + const registered = Symbol.for(key); + const widened: symbol = registered; + return registered; +} + +export function unreachable(key: never): never { + return Symbol.for(key); +} + +export function read(first: K, second: K) { + const firstKey = Symbol.for(first); + const record = { [firstKey]: "first" } as const; + const secondKey = Symbol.for(second); + const value: "first" = record[secondKey]; + return value; +} + +read<"a" | "b">("a", "b");