From 9853f5f271092d02f578faf6c0856d9d85ec7405 Mon Sep 17 00:00:00 2001 From: Michael FIG Date: Mon, 10 Aug 2026 13:32:31 -0600 Subject: [PATCH 01/11] 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 02/11] 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 03/11] 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 04/11] 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 05/11] 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 06/11] 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"); From d91d6e0972685e067988e32aa844cc568723246e Mon Sep 17 00:00:00 2001 From: Michael FIG Date: Fri, 2 Oct 2026 17:21:14 -0600 Subject: [PATCH 07/11] Relate deferred registered symbols through their keys Add regression coverage for generic key relations and symbol union and intersection reduction. Co-authored-by: Codex --- .../typescript/src/enums/typeFlags.enum.ts | 2 +- tsc/internal/checker/checker.go | 12 +- tsc/internal/checker/relater.go | 15 +++ tsc/internal/checker/types.go | 2 +- .../registeredSymbolGenericRelations.symbols | 107 ++++++++++++++++++ .../registeredSymbolGenericRelations.types | 78 +++++++++++++ .../registeredSymbolGenericRelations.ts | 32 ++++++ 7 files changed, 242 insertions(+), 6 deletions(-) create mode 100644 tsc/testdata/baselines/reference/compiler/registeredSymbolGenericRelations.symbols create mode 100644 tsc/testdata/baselines/reference/compiler/registeredSymbolGenericRelations.types create mode 100644 tsc/testdata/tests/cases/compiler/registeredSymbolGenericRelations.ts diff --git a/packages/typescript/src/enums/typeFlags.enum.ts b/packages/typescript/src/enums/typeFlags.enum.ts index 490a8811f7033..1621428605319 100644 --- a/packages/typescript/src/enums/typeFlags.enum.ts +++ b/packages/typescript/src/enums/typeFlags.enum.ts @@ -64,7 +64,7 @@ export enum TypeFlags { 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, + Narrowable = Any | Unknown | StructuredOrInstantiable | StringLike | NumberLike | BigIntLike | BooleanLike | ESSymbolLike | NonPrimitive, IncludesMask = Any | Unknown | Primitive | Never | Object | Union | Intersection | NonPrimitive | TemplateLiteral | StringMapping | RegisteredESSymbol, IncludesMissingType = TypeParameter, IncludesNonWideningType = Index, diff --git a/tsc/internal/checker/checker.go b/tsc/internal/checker/checker.go index a4f11beb04623..6457d663421a2 100644 --- a/tsc/internal/checker/checker.go +++ b/tsc/internal/checker/checker.go @@ -26156,7 +26156,7 @@ func (c *Checker) getUnionTypeWorker(types []*Type, unionReduction UnionReductio typeSet = slices.Delete(typeSet, 1, 2) } } - if includes&(TypeFlagsEnum|TypeFlagsLiteral|TypeFlagsUniqueESSymbol|TypeFlagsTemplateLiteral|TypeFlagsStringMapping) != 0 || + if includes&(TypeFlagsEnum|TypeFlagsLiteral|TypeFlagsUniqueESSymbol|TypeFlagsRegisteredESSymbol|TypeFlagsTemplateLiteral|TypeFlagsStringMapping) != 0 || includes&TypeFlagsVoid != 0 && includes&TypeFlagsUndefined != 0 { typeSet = c.removeRedundantLiteralTypes(typeSet, includes, unionReduction&UnionReductionSubtype != 0) } @@ -26329,7 +26329,7 @@ func (c *Checker) removeRedundantLiteralTypes(types []*Type, includes TypeFlags, remove := flags&(TypeFlagsStringLiteral|TypeFlagsTemplateLiteral|TypeFlagsStringMapping) != 0 && includes&TypeFlagsString != 0 || flags&TypeFlagsNumberLiteral != 0 && includes&TypeFlagsNumber != 0 || flags&TypeFlagsBigIntLiteral != 0 && includes&TypeFlagsBigInt != 0 || - flags&TypeFlagsUniqueESSymbol != 0 && includes&TypeFlagsESSymbol != 0 || + flags&(TypeFlagsUniqueESSymbol|TypeFlagsRegisteredESSymbol) != 0 && includes&TypeFlagsESSymbol != 0 || reduceVoidUndefined && flags&TypeFlagsUndefined != 0 && includes&TypeFlagsVoid != 0 || isFreshLiteralType(t) && containsType(types, t.AsLiteralType().regularType) if remove { @@ -26596,7 +26596,7 @@ func (c *Checker) getIntersectionTypeEx(types []*Type, flags IntersectionFlags, if includes&TypeFlagsString != 0 && includes&(TypeFlagsStringLiteral|TypeFlagsTemplateLiteral|TypeFlagsStringMapping) != 0 || includes&TypeFlagsNumber != 0 && includes&TypeFlagsNumberLiteral != 0 || includes&TypeFlagsBigInt != 0 && includes&TypeFlagsBigIntLiteral != 0 || - includes&TypeFlagsESSymbol != 0 && includes&TypeFlagsUniqueESSymbol != 0 || + includes&TypeFlagsESSymbol != 0 && includes&(TypeFlagsUniqueESSymbol|TypeFlagsRegisteredESSymbol) != 0 || includes&TypeFlagsVoid != 0 && includes&TypeFlagsUndefined != 0 || includes&TypeFlagsIncludesEmptyObject != 0 && includes&TypeFlagsDefinitelyNonNullable != 0 { if flags&IntersectionFlagsNoSupertypeReduction == 0 { @@ -26785,7 +26785,7 @@ func (c *Checker) removeRedundantSupertypes(types []*Type, includes TypeFlags) [ remove := t.flags&TypeFlagsString != 0 && includes&(TypeFlagsStringLiteral|TypeFlagsTemplateLiteral|TypeFlagsStringMapping) != 0 || t.flags&TypeFlagsNumber != 0 && includes&TypeFlagsNumberLiteral != 0 || t.flags&TypeFlagsBigInt != 0 && includes&TypeFlagsBigIntLiteral != 0 || - t.flags&TypeFlagsESSymbol != 0 && includes&TypeFlagsUniqueESSymbol != 0 || + t.flags&TypeFlagsESSymbol != 0 && includes&(TypeFlagsUniqueESSymbol|TypeFlagsRegisteredESSymbol) != 0 || t.flags&TypeFlagsVoid != 0 && includes&TypeFlagsUndefined != 0 || c.IsEmptyAnonymousObjectType(t) && includes&TypeFlagsDefinitelyNonNullable != 0 if remove { @@ -28033,6 +28033,10 @@ func (c *Checker) computeBaseConstraint(t *Type, stack []RecursionId) *Type { } return c.stringType case t.flags&TypeFlagsRegisteredESSymbol != 0: + constraint := c.getNextBaseConstraint(t.Target(), stack) + if constraint != nil && constraint != t.Target() { + return c.getRegisteredESSymbolType(constraint, t.alias) + } return c.esSymbolType case t.flags&TypeFlagsIndexedAccess != 0: if c.isMappedTypeGenericIndexedAccess(t) { diff --git a/tsc/internal/checker/relater.go b/tsc/internal/checker/relater.go index 430f0c02a5c70..b6554b1e0a1e7 100644 --- a/tsc/internal/checker/relater.go +++ b/tsc/internal/checker/relater.go @@ -3831,6 +3831,21 @@ func (r *Relater) structuredTypeRelatedToWorker(source *Type, target *Type, repo } } } + case source.flags&TypeFlagsRegisteredESSymbol != 0: + if target.flags&TypeFlagsRegisteredESSymbol != 0 { + result = r.isRelatedTo(source.Target(), target.Target(), RecursionFlagsBoth, reportErrors) + if result != TernaryFalse { + return result + } + } else { + constraint := r.c.getBaseConstraintOfType(source) + if constraint != nil { + result = r.isRelatedTo(constraint, target, RecursionFlagsSource, reportErrors) + if result != TernaryFalse { + return result + } + } + } default: // An empty object type is related to any mapped type that includes a '?' modifier. if r.relation != r.c.subtypeRelation && r.relation != r.c.strictSubtypeRelation && isPartialMappedType(target) && r.c.isEmptyObjectType(source) { diff --git a/tsc/internal/checker/types.go b/tsc/internal/checker/types.go index 157394867f63a..7c97e48a64e80 100644 --- a/tsc/internal/checker/types.go +++ b/tsc/internal/checker/types.go @@ -503,7 +503,7 @@ const ( TypeFlagsSingleton = TypeFlagsAny | TypeFlagsUnknown | TypeFlagsString | TypeFlagsNumber | TypeFlagsBoolean | TypeFlagsBigInt | TypeFlagsESSymbol | TypeFlagsVoid | TypeFlagsUndefined | TypeFlagsNull | TypeFlagsNever | TypeFlagsNonPrimitive // 'TypeFlagsNarrowable' types are types where narrowing actually narrows. // This *should* be every type other than null, undefined, void, and never - TypeFlagsNarrowable = TypeFlagsAny | TypeFlagsUnknown | TypeFlagsStructuredOrInstantiable | TypeFlagsStringLike | TypeFlagsNumberLike | TypeFlagsBigIntLike | TypeFlagsBooleanLike | TypeFlagsESSymbol | TypeFlagsUniqueESSymbol | TypeFlagsNonPrimitive + TypeFlagsNarrowable = TypeFlagsAny | TypeFlagsUnknown | TypeFlagsStructuredOrInstantiable | TypeFlagsStringLike | TypeFlagsNumberLike | TypeFlagsBigIntLike | TypeFlagsBooleanLike | TypeFlagsESSymbolLike | TypeFlagsNonPrimitive // The following flags are aggregated during union and intersection type construction 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 diff --git a/tsc/testdata/baselines/reference/compiler/registeredSymbolGenericRelations.symbols b/tsc/testdata/baselines/reference/compiler/registeredSymbolGenericRelations.symbols new file mode 100644 index 0000000000000..cded039b62e43 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/registeredSymbolGenericRelations.symbols @@ -0,0 +1,107 @@ +//// [tests/cases/compiler/registeredSymbolGenericRelations.ts] //// + +=== registeredSymbolGenericRelations.ts === +type Equal = +>Equal : Symbol(Equal, Decl(registeredSymbolGenericRelations.ts, 0, 0)) +>A : Symbol(A, Decl(registeredSymbolGenericRelations.ts, 0, 11)) +>B : Symbol(B, Decl(registeredSymbolGenericRelations.ts, 0, 13)) + + (() => T extends A ? 1 : 2) extends +>T : Symbol(T, Decl(registeredSymbolGenericRelations.ts, 1, 6)) +>T : Symbol(T, Decl(registeredSymbolGenericRelations.ts, 1, 6)) +>A : Symbol(A, Decl(registeredSymbolGenericRelations.ts, 0, 11)) + + (() => T extends B ? 1 : 2) ? true : false; +>T : Symbol(T, Decl(registeredSymbolGenericRelations.ts, 2, 6)) +>T : Symbol(T, Decl(registeredSymbolGenericRelations.ts, 2, 6)) +>B : Symbol(B, Decl(registeredSymbolGenericRelations.ts, 0, 13)) + +declare function inferKey(value: RegisteredSymbol): K; +>inferKey : Symbol(inferKey, Decl(registeredSymbolGenericRelations.ts, 2, 50)) +>K : Symbol(K, Decl(registeredSymbolGenericRelations.ts, 4, 26)) +>value : Symbol(value, Decl(registeredSymbolGenericRelations.ts, 4, 44)) +>RegisteredSymbol : Symbol(RegisteredSymbol, Decl(lib.es2015.symbol.d.ts, --, --)) +>K : Symbol(K, Decl(registeredSymbolGenericRelations.ts, 4, 26)) +>K : Symbol(K, Decl(registeredSymbolGenericRelations.ts, 4, 26)) + +const inferred: "foo" = inferKey(Symbol.for("foo")); +>inferred : Symbol(inferred, Decl(registeredSymbolGenericRelations.ts, 5, 5)) +>inferKey : Symbol(inferKey, Decl(registeredSymbolGenericRelations.ts, 2, 50)) +>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, --, --)) + +function simplify() { +>simplify : Symbol(simplify, Decl(registeredSymbolGenericRelations.ts, 5, 52)) +>K : Symbol(K, Decl(registeredSymbolGenericRelations.ts, 7, 18)) + + const unionIsSymbol: true = null! as Equal | symbol, symbol>; +>unionIsSymbol : Symbol(unionIsSymbol, Decl(registeredSymbolGenericRelations.ts, 8, 9)) +>Equal : Symbol(Equal, Decl(registeredSymbolGenericRelations.ts, 0, 0)) +>RegisteredSymbol : Symbol(RegisteredSymbol, Decl(lib.es2015.symbol.d.ts, --, --)) +>K : Symbol(K, Decl(registeredSymbolGenericRelations.ts, 7, 18)) + + const intersectionIsRegistered: true = null! as Equal & symbol, RegisteredSymbol>; +>intersectionIsRegistered : Symbol(intersectionIsRegistered, Decl(registeredSymbolGenericRelations.ts, 9, 9)) +>Equal : Symbol(Equal, Decl(registeredSymbolGenericRelations.ts, 0, 0)) +>RegisteredSymbol : Symbol(RegisteredSymbol, Decl(lib.es2015.symbol.d.ts, --, --)) +>K : Symbol(K, Decl(registeredSymbolGenericRelations.ts, 7, 18)) +>RegisteredSymbol : Symbol(RegisteredSymbol, Decl(lib.es2015.symbol.d.ts, --, --)) +>K : Symbol(K, Decl(registeredSymbolGenericRelations.ts, 7, 18)) + + return { unionIsSymbol, intersectionIsRegistered }; +>unionIsSymbol : Symbol(unionIsSymbol, Decl(registeredSymbolGenericRelations.ts, 10, 12)) +>intersectionIsRegistered : Symbol(intersectionIsRegistered, Decl(registeredSymbolGenericRelations.ts, 10, 27)) +} + +function widenKey(value: RegisteredSymbol): RegisteredSymbol<"foo" | "bar"> { +>widenKey : Symbol(widenKey, Decl(registeredSymbolGenericRelations.ts, 11, 1)) +>K : Symbol(K, Decl(registeredSymbolGenericRelations.ts, 13, 18)) +>value : Symbol(value, Decl(registeredSymbolGenericRelations.ts, 13, 43)) +>RegisteredSymbol : Symbol(RegisteredSymbol, Decl(lib.es2015.symbol.d.ts, --, --)) +>K : Symbol(K, Decl(registeredSymbolGenericRelations.ts, 13, 18)) +>RegisteredSymbol : Symbol(RegisteredSymbol, Decl(lib.es2015.symbol.d.ts, --, --)) + + return value; +>value : Symbol(value, Decl(registeredSymbolGenericRelations.ts, 13, 43)) +} + +function widenGeneric(value: RegisteredSymbol): RegisteredSymbol { +>widenGeneric : Symbol(widenGeneric, Decl(registeredSymbolGenericRelations.ts, 15, 1)) +>K : Symbol(K, Decl(registeredSymbolGenericRelations.ts, 17, 22)) +>L : Symbol(L, Decl(registeredSymbolGenericRelations.ts, 17, 34)) +>L : Symbol(L, Decl(registeredSymbolGenericRelations.ts, 17, 34)) +>value : Symbol(value, Decl(registeredSymbolGenericRelations.ts, 17, 53)) +>RegisteredSymbol : Symbol(RegisteredSymbol, Decl(lib.es2015.symbol.d.ts, --, --)) +>K : Symbol(K, Decl(registeredSymbolGenericRelations.ts, 17, 22)) +>RegisteredSymbol : Symbol(RegisteredSymbol, Decl(lib.es2015.symbol.d.ts, --, --)) +>L : Symbol(L, Decl(registeredSymbolGenericRelations.ts, 17, 34)) + + return value; +>value : Symbol(value, Decl(registeredSymbolGenericRelations.ts, 17, 53)) +} + +function commonSymbol(value: RegisteredSymbol): symbol { +>commonSymbol : Symbol(commonSymbol, Decl(registeredSymbolGenericRelations.ts, 19, 1)) +>K : Symbol(K, Decl(registeredSymbolGenericRelations.ts, 21, 22)) +>value : Symbol(value, Decl(registeredSymbolGenericRelations.ts, 21, 40)) +>RegisteredSymbol : Symbol(RegisteredSymbol, Decl(lib.es2015.symbol.d.ts, --, --)) +>K : Symbol(K, Decl(registeredSymbolGenericRelations.ts, 21, 22)) + + return value; +>value : Symbol(value, Decl(registeredSymbolGenericRelations.ts, 21, 40)) +} + +function intersect(value: RegisteredSymbol): RegisteredSymbol & symbol { +>intersect : Symbol(intersect, Decl(registeredSymbolGenericRelations.ts, 23, 1)) +>K : Symbol(K, Decl(registeredSymbolGenericRelations.ts, 25, 19)) +>value : Symbol(value, Decl(registeredSymbolGenericRelations.ts, 25, 37)) +>RegisteredSymbol : Symbol(RegisteredSymbol, Decl(lib.es2015.symbol.d.ts, --, --)) +>K : Symbol(K, Decl(registeredSymbolGenericRelations.ts, 25, 19)) +>RegisteredSymbol : Symbol(RegisteredSymbol, Decl(lib.es2015.symbol.d.ts, --, --)) +>K : Symbol(K, Decl(registeredSymbolGenericRelations.ts, 25, 19)) + + return value; +>value : Symbol(value, Decl(registeredSymbolGenericRelations.ts, 25, 37)) +} + diff --git a/tsc/testdata/baselines/reference/compiler/registeredSymbolGenericRelations.types b/tsc/testdata/baselines/reference/compiler/registeredSymbolGenericRelations.types new file mode 100644 index 0000000000000..c9d46c09a2897 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/registeredSymbolGenericRelations.types @@ -0,0 +1,78 @@ +//// [tests/cases/compiler/registeredSymbolGenericRelations.ts] //// + +=== registeredSymbolGenericRelations.ts === +type Equal = +>Equal : Equal + + (() => T extends A ? 1 : 2) extends + (() => T extends B ? 1 : 2) ? true : false; +>true : true +>false : false + +declare function inferKey(value: RegisteredSymbol): K; +>inferKey : (value: RegisteredSymbol) => K +>value : RegisteredSymbol + +const inferred: "foo" = inferKey(Symbol.for("foo")); +>inferred : "foo" +>inferKey(Symbol.for("foo")) : "foo" +>inferKey : (value: RegisteredSymbol) => K +>Symbol.for("foo") : RegisteredSymbol<"foo"> +>Symbol.for : (key: Key) => RegisteredSymbol +>Symbol : SymbolConstructor +>for : (key: Key) => RegisteredSymbol +>"foo" : "foo" + +function simplify() { +>simplify : () => { unionIsSymbol: true; intersectionIsRegistered: true; } + + const unionIsSymbol: true = null! as Equal | symbol, symbol>; +>unionIsSymbol : true +>true : true +>null! as Equal | symbol, symbol> : true +>null! : never + + const intersectionIsRegistered: true = null! as Equal & symbol, RegisteredSymbol>; +>intersectionIsRegistered : true +>true : true +>null! as Equal & symbol, RegisteredSymbol> : true +>null! : never + + return { unionIsSymbol, intersectionIsRegistered }; +>{ unionIsSymbol, intersectionIsRegistered } : { unionIsSymbol: true; intersectionIsRegistered: true; } +>unionIsSymbol : true +>intersectionIsRegistered : true +} + +function widenKey(value: RegisteredSymbol): RegisteredSymbol<"foo" | "bar"> { +>widenKey : (value: RegisteredSymbol) => RegisteredSymbol<"foo" | "bar"> +>value : RegisteredSymbol + + return value; +>value : RegisteredSymbol<"bar"> | RegisteredSymbol<"foo"> +} + +function widenGeneric(value: RegisteredSymbol): RegisteredSymbol { +>widenGeneric : (value: RegisteredSymbol) => RegisteredSymbol +>value : RegisteredSymbol + + return value; +>value : RegisteredSymbol +} + +function commonSymbol(value: RegisteredSymbol): symbol { +>commonSymbol : (value: RegisteredSymbol) => symbol +>value : RegisteredSymbol + + return value; +>value : RegisteredSymbol +} + +function intersect(value: RegisteredSymbol): RegisteredSymbol & symbol { +>intersect : (value: RegisteredSymbol) => RegisteredSymbol & symbol +>value : RegisteredSymbol + + return value; +>value : RegisteredSymbol +} + diff --git a/tsc/testdata/tests/cases/compiler/registeredSymbolGenericRelations.ts b/tsc/testdata/tests/cases/compiler/registeredSymbolGenericRelations.ts new file mode 100644 index 0000000000000..569354aaa0d7a --- /dev/null +++ b/tsc/testdata/tests/cases/compiler/registeredSymbolGenericRelations.ts @@ -0,0 +1,32 @@ +// @target: es2015 +// @strict: true +// @noEmit: true + +type Equal = + (() => T extends A ? 1 : 2) extends + (() => T extends B ? 1 : 2) ? true : false; + +declare function inferKey(value: RegisteredSymbol): K; +const inferred: "foo" = inferKey(Symbol.for("foo")); + +function simplify() { + const unionIsSymbol: true = null! as Equal | symbol, symbol>; + const intersectionIsRegistered: true = null! as Equal & symbol, RegisteredSymbol>; + return { unionIsSymbol, intersectionIsRegistered }; +} + +function widenKey(value: RegisteredSymbol): RegisteredSymbol<"foo" | "bar"> { + return value; +} + +function widenGeneric(value: RegisteredSymbol): RegisteredSymbol { + return value; +} + +function commonSymbol(value: RegisteredSymbol): symbol { + return value; +} + +function intersect(value: RegisteredSymbol): RegisteredSymbol & symbol { + return value; +} From 39605ea75797cd9652ae3b76a576de40e7002627 Mon Sep 17 00:00:00 2001 From: Michael FIG Date: Fri, 2 Oct 2026 22:40:41 -0600 Subject: [PATCH 08/11] Emit type queries for inaccessible unique symbol aliases Preserve const alias identities in declaration output and refresh the unique-symbol declaration baselines. Co-authored-by: Codex --- tsc/internal/checker/nodebuilderimpl.go | 8 ++++++ .../conformance/uniqueSymbolsDeclarations.js | 28 +++++++++---------- .../uniqueSymbolsDeclarations.types | 28 +++++++++---------- 3 files changed, 36 insertions(+), 28 deletions(-) diff --git a/tsc/internal/checker/nodebuilderimpl.go b/tsc/internal/checker/nodebuilderimpl.go index 9c7db3bd855e3..289b2ba52a754 100644 --- a/tsc/internal/checker/nodebuilderimpl.go +++ b/tsc/internal/checker/nodebuilderimpl.go @@ -2352,6 +2352,14 @@ func (b *NodeBuilderImpl) serializeTypeForDeclaration(declaration *ast.Declarati remove() } } + if result == nil { + if declaration != nil && ast.IsVariableDeclaration(declaration) && t.flags&TypeFlagsUniqueESSymbol != 0 && !b.ch.IsValueSymbolAccessible(t.symbol, b.ctx.enclosingDeclaration) { + initializer := declaration.Initializer() + if initializer != nil && ast.IsEntityNameExpression(initializer) { + result = b.f.NewTypeQueryNode(b.f.DeepCloneNode(initializer), nil) + } + } + } if result == nil { if reportedInferenceFallback { oldSuppress := b.ctx.suppressReportInferenceFallback diff --git a/tsc/testdata/baselines/reference/conformance/uniqueSymbolsDeclarations.js b/tsc/testdata/baselines/reference/conformance/uniqueSymbolsDeclarations.js index df669ec3b1c74..08785dfcc7c2e 100644 --- a/tsc/testdata/baselines/reference/conformance/uniqueSymbolsDeclarations.js +++ b/tsc/testdata/baselines/reference/conformance/uniqueSymbolsDeclarations.js @@ -415,10 +415,10 @@ declare let letCall: symbol; declare var varCall: symbol; declare const constType: unique symbol; declare const constTypeAndCall: unique symbol; -declare const constInitToConstCall: symbol; +declare const constInitToConstCall: typeof constCall; declare const constInitToLetCall: symbol; declare const constInitToVarCall: symbol; -declare const constInitToConstDeclAmbient: symbol; +declare const constInitToConstDeclAmbient: typeof constType; declare let letInitToConstCall: symbol; declare let letInitToLetCall: symbol; declare let letInitToVarCall: symbol; @@ -452,9 +452,9 @@ declare class C { readwriteCall: symbol; } declare const c: C; -declare const constInitToCReadonlyStaticCall: symbol; -declare const constInitToCReadonlyStaticType: symbol; -declare const constInitToCReadonlyStaticTypeAndCall: symbol; +declare const constInitToCReadonlyStaticCall: typeof C.readonlyStaticCall; +declare const constInitToCReadonlyStaticType: typeof C.readonlyStaticType; +declare const constInitToCReadonlyStaticTypeAndCall: typeof C.readonlyStaticTypeAndCall; declare const constInitToCReadwriteStaticCall: symbol; declare const constInitToCReadonlyStaticCallWithTypeQuery: typeof C.readonlyStaticCall; declare const constInitToCReadonlyStaticTypeWithTypeQuery: typeof C.readonlyStaticType; @@ -470,7 +470,7 @@ interface I { readonly readonlyType: unique symbol; } declare const i: I; -declare const constInitToIReadonlyType: symbol; +declare const constInitToIReadonlyType: I["readonlyType"]; declare const constInitToIReadonlyTypeWithTypeQuery: typeof i.readonlyType; declare const constInitToIReadonlyTypeWithIndexedAccess: I["readonlyType"]; type L = { @@ -480,8 +480,8 @@ type L = { }; }; declare const l: L; -declare const constInitToLReadonlyType: symbol; -declare const constInitToLReadonlyNestedType: symbol; +declare const constInitToLReadonlyType: typeof l.readonlyType; +declare const constInitToLReadonlyNestedType: typeof l.nested.readonlyNestedType; declare const constInitToLReadonlyTypeWithTypeQuery: typeof l.readonlyType; declare const constInitToLReadonlyNestedTypeWithTypeQuery: typeof l.nested.readonlyNestedType; declare const constInitToLReadonlyTypeWithIndexedAccess: L["readonlyType"]; @@ -510,15 +510,15 @@ declare const o2: { method5(p?: symbol): symbol; }; declare class C0 { - static readonly a: symbol; - static readonly b: symbol; - static readonly c: symbol; + static readonly a: typeof s; + static readonly b: typeof N.s; + static readonly c: typeof N.s; static d: symbol; static e: symbol; static f: symbol; - readonly a: symbol; - readonly b: symbol; - readonly c: symbol; + readonly a: typeof s; + readonly b: typeof N.s; + readonly c: typeof N.s; d: symbol; e: symbol; f: symbol; diff --git a/tsc/testdata/baselines/reference/conformance/uniqueSymbolsDeclarations.types b/tsc/testdata/baselines/reference/conformance/uniqueSymbolsDeclarations.types index 5f22b96c2573c..82cd1c8837849 100644 --- a/tsc/testdata/baselines/reference/conformance/uniqueSymbolsDeclarations.types +++ b/tsc/testdata/baselines/reference/conformance/uniqueSymbolsDeclarations.types @@ -29,7 +29,7 @@ const constTypeAndCall: unique symbol = Symbol(); // declaration from initializer const constInitToConstCall = constCall; ->constInitToConstCall : symbol +>constInitToConstCall : unique symbol >constCall : unique symbol const constInitToLetCall = letCall; @@ -41,7 +41,7 @@ const constInitToVarCall = varCall; >varCall : symbol const constInitToConstDeclAmbient = constType; ->constInitToConstDeclAmbient : symbol +>constInitToConstDeclAmbient : unique symbol >constType : unique symbol let letInitToConstCall = constCall; @@ -194,19 +194,19 @@ declare const c: C; >c : C const constInitToCReadonlyStaticCall = C.readonlyStaticCall; ->constInitToCReadonlyStaticCall : symbol +>constInitToCReadonlyStaticCall : unique symbol >C.readonlyStaticCall : unique symbol >C : typeof C >readonlyStaticCall : unique symbol const constInitToCReadonlyStaticType = C.readonlyStaticType; ->constInitToCReadonlyStaticType : symbol +>constInitToCReadonlyStaticType : unique symbol >C.readonlyStaticType : unique symbol >C : typeof C >readonlyStaticType : unique symbol const constInitToCReadonlyStaticTypeAndCall = C.readonlyStaticTypeAndCall; ->constInitToCReadonlyStaticTypeAndCall : symbol +>constInitToCReadonlyStaticTypeAndCall : unique symbol >C.readonlyStaticTypeAndCall : unique symbol >C : typeof C >readonlyStaticTypeAndCall : unique symbol @@ -304,7 +304,7 @@ declare const i: I; >i : I const constInitToIReadonlyType = i.readonlyType; ->constInitToIReadonlyType : symbol +>constInitToIReadonlyType : unique symbol >i.readonlyType : unique symbol >i : I >readonlyType : unique symbol @@ -342,13 +342,13 @@ declare const l: L; >l : L const constInitToLReadonlyType = l.readonlyType; ->constInitToLReadonlyType : symbol +>constInitToLReadonlyType : unique symbol >l.readonlyType : unique symbol >l : L >readonlyType : unique symbol const constInitToLReadonlyNestedType = l.nested.readonlyNestedType; ->constInitToLReadonlyNestedType : symbol +>constInitToLReadonlyNestedType : unique symbol >l.nested.readonlyNestedType : unique symbol >l.nested : { readonly readonlyNestedType: unique symbol; } >l : L @@ -529,17 +529,17 @@ class C0 { >C0 : C0 static readonly a = s; ->a : symbol +>a : unique symbol >s : unique symbol static readonly b = N.s; ->b : symbol +>b : unique symbol >N.s : unique symbol >N : typeof N >s : unique symbol static readonly c = N["s"]; ->c : symbol +>c : unique symbol >N["s"] : unique symbol >N : typeof N >"s" : "s" @@ -561,17 +561,17 @@ class C0 { >"s" : "s" readonly a = s; ->a : symbol +>a : unique symbol >s : unique symbol readonly b = N.s; ->b : symbol +>b : unique symbol >N.s : unique symbol >N : typeof N >s : unique symbol readonly c = N["s"]; ->c : symbol +>c : unique symbol >N["s"] : unique symbol >N : typeof N >"s" : "s" From 8ed748a57a53caa0bb0402409192be3a16702dbf Mon Sep 17 00:00:00 2001 From: Michael FIG Date: Fri, 2 Oct 2026 23:12:48 -0600 Subject: [PATCH 09/11] Accept intended symbol behavior baselines Refresh 19 type, symbol, and diagnostic baselines while leaving the computed registered-symbol type baseline for further investigation. Co-authored-by: Codex --- ...uNeedToChangeYourTargetLibraryES2015.types | 10 +++---- .../objectLiteralPropertyImplicitlyAny.types | 10 +++---- .../superSymbolIndexedAccess1.types | 6 ++-- .../superSymbolIndexedAccess3.types | 6 ++-- .../superSymbolIndexedAccess4.types | 6 ++-- .../conformance/symbolProperty53.errors.txt | 4 +-- .../conformance/symbolProperty53.types | 8 +++--- .../reference/conformance/symbolType10.types | 6 ++-- .../reference/conformance/symbolType11.types | 6 ++-- .../reference/conformance/symbolType12.types | 6 ++-- .../reference/conformance/symbolType4.types | 6 ++-- .../reference/conformance/symbolType5.types | 6 ++-- .../reference/conformance/symbolType6.types | 6 ++-- .../reference/conformance/symbolType7.types | 6 ++-- .../reference/conformance/symbolType8.types | 6 ++-- .../reference/conformance/symbolType9.types | 6 ++-- .../reference/conformance/uniqueSymbols.types | 28 +++++++++---------- .../uniqueSymbolsPropertyNames.errors.txt | 22 +++++++++++---- .../uniqueSymbolsPropertyNames.symbols | 8 +++--- 19 files changed, 87 insertions(+), 75 deletions(-) diff --git a/tsc/testdata/baselines/reference/compiler/doYouNeedToChangeYourTargetLibraryES2015.types b/tsc/testdata/baselines/reference/compiler/doYouNeedToChangeYourTargetLibraryES2015.types index d383a738b8790..db2e89fc734a8 100644 --- a/tsc/testdata/baselines/reference/compiler/doYouNeedToChangeYourTargetLibraryES2015.types +++ b/tsc/testdata/baselines/reference/compiler/doYouNeedToChangeYourTargetLibraryES2015.types @@ -472,11 +472,11 @@ const testPromiseReject = Promise.reject(); >reject : (reason?: any) => Promise const testSymbolFor = Symbol.for('a'); ->testSymbolFor : unique symbol ->Symbol.for('a') : unique symbol ->Symbol.for : (key: string) => symbol +>testSymbolFor : RegisteredSymbol<"a"> +>Symbol.for('a') : RegisteredSymbol<"a"> +>Symbol.for : (key: Key) => RegisteredSymbol >Symbol : SymbolConstructor ->for : (key: string) => symbol +>for : (key: Key) => RegisteredSymbol >'a' : "a" const testSymbolKeyFor = Symbol.keyFor(testSymbolFor); @@ -485,7 +485,7 @@ const testSymbolKeyFor = Symbol.keyFor(testSymbolFor); >Symbol.keyFor : (sym: symbol) => string | undefined >Symbol : SymbolConstructor >keyFor : (sym: symbol) => string | undefined ->testSymbolFor : unique symbol +>testSymbolFor : RegisteredSymbol<"a"> const testWeakMap: WeakMap = null as any; >testWeakMap : WeakMap diff --git a/tsc/testdata/baselines/reference/compiler/objectLiteralPropertyImplicitlyAny.types b/tsc/testdata/baselines/reference/compiler/objectLiteralPropertyImplicitlyAny.types index 4e3af7fa9fafa..1660594cd2f93 100644 --- a/tsc/testdata/baselines/reference/compiler/objectLiteralPropertyImplicitlyAny.types +++ b/tsc/testdata/baselines/reference/compiler/objectLiteralPropertyImplicitlyAny.types @@ -2,17 +2,17 @@ === objectLiteralPropertyImplicitlyAny.ts === const foo = Symbol.for("foo"); ->foo : unique symbol ->Symbol.for("foo") : unique symbol ->Symbol.for : (key: string) => symbol +>foo : RegisteredSymbol<"foo"> +>Symbol.for("foo") : RegisteredSymbol<"foo"> +>Symbol.for : (key: Key) => RegisteredSymbol >Symbol : SymbolConstructor ->for : (key: string) => symbol +>for : (key: Key) => RegisteredSymbol >"foo" : "foo" const o = { [foo]: undefined }; >o : { [foo]: undefined; } >{ [foo]: undefined } : { [foo]: undefined; } >[foo] : undefined ->foo : unique symbol +>foo : RegisteredSymbol<"foo"> >undefined : undefined diff --git a/tsc/testdata/baselines/reference/conformance/superSymbolIndexedAccess1.types b/tsc/testdata/baselines/reference/conformance/superSymbolIndexedAccess1.types index 5f5e70552c541..ac2d28394106c 100644 --- a/tsc/testdata/baselines/reference/conformance/superSymbolIndexedAccess1.types +++ b/tsc/testdata/baselines/reference/conformance/superSymbolIndexedAccess1.types @@ -3,10 +3,10 @@ === superSymbolIndexedAccess1.ts === var symbol = Symbol.for('myThing'); >symbol : symbol ->Symbol.for('myThing') : symbol ->Symbol.for : (key: string) => symbol +>Symbol.for('myThing') : RegisteredSymbol<"myThing"> +>Symbol.for : (key: Key) => RegisteredSymbol >Symbol : SymbolConstructor ->for : (key: string) => symbol +>for : (key: Key) => RegisteredSymbol >'myThing' : "myThing" class Foo { diff --git a/tsc/testdata/baselines/reference/conformance/superSymbolIndexedAccess3.types b/tsc/testdata/baselines/reference/conformance/superSymbolIndexedAccess3.types index 5e1eb518d970b..0b6db132cbd4b 100644 --- a/tsc/testdata/baselines/reference/conformance/superSymbolIndexedAccess3.types +++ b/tsc/testdata/baselines/reference/conformance/superSymbolIndexedAccess3.types @@ -3,10 +3,10 @@ === superSymbolIndexedAccess3.ts === var symbol = Symbol.for('myThing'); >symbol : symbol ->Symbol.for('myThing') : symbol ->Symbol.for : (key: string) => symbol +>Symbol.for('myThing') : RegisteredSymbol<"myThing"> +>Symbol.for : (key: Key) => RegisteredSymbol >Symbol : SymbolConstructor ->for : (key: string) => symbol +>for : (key: Key) => RegisteredSymbol >'myThing' : "myThing" class Foo { diff --git a/tsc/testdata/baselines/reference/conformance/superSymbolIndexedAccess4.types b/tsc/testdata/baselines/reference/conformance/superSymbolIndexedAccess4.types index 88170be4341f9..7aa1497a54204 100644 --- a/tsc/testdata/baselines/reference/conformance/superSymbolIndexedAccess4.types +++ b/tsc/testdata/baselines/reference/conformance/superSymbolIndexedAccess4.types @@ -3,10 +3,10 @@ === superSymbolIndexedAccess4.ts === var symbol = Symbol.for('myThing'); >symbol : symbol ->Symbol.for('myThing') : symbol ->Symbol.for : (key: string) => symbol +>Symbol.for('myThing') : RegisteredSymbol<"myThing"> +>Symbol.for : (key: Key) => RegisteredSymbol >Symbol : SymbolConstructor ->for : (key: string) => symbol +>for : (key: Key) => RegisteredSymbol >'myThing' : "myThing" class Bar { diff --git a/tsc/testdata/baselines/reference/conformance/symbolProperty53.errors.txt b/tsc/testdata/baselines/reference/conformance/symbolProperty53.errors.txt index 096d453cbd652..9ca661b922dc9 100644 --- a/tsc/testdata/baselines/reference/conformance/symbolProperty53.errors.txt +++ b/tsc/testdata/baselines/reference/conformance/symbolProperty53.errors.txt @@ -1,5 +1,5 @@ symbolProperty53.ts(2,5): error TS2464: A computed property name must be of type 'string', 'number', 'symbol', or 'any'. -symbolProperty53.ts(5,5): error TS2538: Type '(key: string) => symbol' cannot be used as an index type. +symbolProperty53.ts(5,5): error TS2538: Type '(key: Key) => RegisteredSymbol' cannot be used as an index type. ==== symbolProperty53.ts (2 errors) ==== @@ -11,4 +11,4 @@ symbolProperty53.ts(5,5): error TS2538: Type '(key: string) => symbol' cannot be obj[Symbol.for]; ~~~~~~~~~~ -!!! error TS2538: Type '(key: string) => symbol' cannot be used as an index type. \ No newline at end of file +!!! error TS2538: Type '(key: Key) => RegisteredSymbol' cannot be used as an index type. \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/conformance/symbolProperty53.types b/tsc/testdata/baselines/reference/conformance/symbolProperty53.types index 92d5254c63f6c..036ca190ff45f 100644 --- a/tsc/testdata/baselines/reference/conformance/symbolProperty53.types +++ b/tsc/testdata/baselines/reference/conformance/symbolProperty53.types @@ -7,9 +7,9 @@ var obj = { [Symbol.for]: 0 >[Symbol.for] : number ->Symbol.for : (key: string) => symbol +>Symbol.for : (key: Key) => RegisteredSymbol >Symbol : SymbolConstructor ->for : (key: string) => symbol +>for : (key: Key) => RegisteredSymbol >0 : 0 }; @@ -17,7 +17,7 @@ var obj = { obj[Symbol.for]; >obj[Symbol.for] : any >obj : {} ->Symbol.for : (key: string) => symbol +>Symbol.for : (key: Key) => RegisteredSymbol >Symbol : SymbolConstructor ->for : (key: string) => symbol +>for : (key: Key) => RegisteredSymbol diff --git a/tsc/testdata/baselines/reference/conformance/symbolType10.types b/tsc/testdata/baselines/reference/conformance/symbolType10.types index d42b177f8e738..a647762dc5e4b 100644 --- a/tsc/testdata/baselines/reference/conformance/symbolType10.types +++ b/tsc/testdata/baselines/reference/conformance/symbolType10.types @@ -3,10 +3,10 @@ === symbolType10.ts === var s = Symbol.for("bitwise"); >s : symbol ->Symbol.for("bitwise") : symbol ->Symbol.for : (key: string) => symbol +>Symbol.for("bitwise") : RegisteredSymbol<"bitwise"> +>Symbol.for : (key: Key) => RegisteredSymbol >Symbol : SymbolConstructor ->for : (key: string) => symbol +>for : (key: Key) => RegisteredSymbol >"bitwise" : "bitwise" s & s; diff --git a/tsc/testdata/baselines/reference/conformance/symbolType11.types b/tsc/testdata/baselines/reference/conformance/symbolType11.types index ce5139c311275..1e5390bb6d54b 100644 --- a/tsc/testdata/baselines/reference/conformance/symbolType11.types +++ b/tsc/testdata/baselines/reference/conformance/symbolType11.types @@ -3,10 +3,10 @@ === symbolType11.ts === var s = Symbol.for("logical"); >s : symbol ->Symbol.for("logical") : symbol ->Symbol.for : (key: string) => symbol +>Symbol.for("logical") : RegisteredSymbol<"logical"> +>Symbol.for : (key: Key) => RegisteredSymbol >Symbol : SymbolConstructor ->for : (key: string) => symbol +>for : (key: Key) => RegisteredSymbol >"logical" : "logical" s && s; diff --git a/tsc/testdata/baselines/reference/conformance/symbolType12.types b/tsc/testdata/baselines/reference/conformance/symbolType12.types index 476e718bbc6fb..a2942c4339047 100644 --- a/tsc/testdata/baselines/reference/conformance/symbolType12.types +++ b/tsc/testdata/baselines/reference/conformance/symbolType12.types @@ -3,10 +3,10 @@ === symbolType12.ts === var s = Symbol.for("assign"); >s : symbol ->Symbol.for("assign") : symbol ->Symbol.for : (key: string) => symbol +>Symbol.for("assign") : RegisteredSymbol<"assign"> +>Symbol.for : (key: Key) => RegisteredSymbol >Symbol : SymbolConstructor ->for : (key: string) => symbol +>for : (key: Key) => RegisteredSymbol >"assign" : "assign" var str = ""; diff --git a/tsc/testdata/baselines/reference/conformance/symbolType4.types b/tsc/testdata/baselines/reference/conformance/symbolType4.types index 7d365d19d4357..04897eaa14de5 100644 --- a/tsc/testdata/baselines/reference/conformance/symbolType4.types +++ b/tsc/testdata/baselines/reference/conformance/symbolType4.types @@ -3,10 +3,10 @@ === symbolType4.ts === var s = Symbol.for("postfix"); >s : symbol ->Symbol.for("postfix") : symbol ->Symbol.for : (key: string) => symbol +>Symbol.for("postfix") : RegisteredSymbol<"postfix"> +>Symbol.for : (key: Key) => RegisteredSymbol >Symbol : SymbolConstructor ->for : (key: string) => symbol +>for : (key: Key) => RegisteredSymbol >"postfix" : "postfix" s++; diff --git a/tsc/testdata/baselines/reference/conformance/symbolType5.types b/tsc/testdata/baselines/reference/conformance/symbolType5.types index 67d5c757a9a7a..a4a3f9a69d603 100644 --- a/tsc/testdata/baselines/reference/conformance/symbolType5.types +++ b/tsc/testdata/baselines/reference/conformance/symbolType5.types @@ -3,10 +3,10 @@ === symbolType5.ts === var s = Symbol.for("multiply"); >s : symbol ->Symbol.for("multiply") : symbol ->Symbol.for : (key: string) => symbol +>Symbol.for("multiply") : RegisteredSymbol<"multiply"> +>Symbol.for : (key: Key) => RegisteredSymbol >Symbol : SymbolConstructor ->for : (key: string) => symbol +>for : (key: Key) => RegisteredSymbol >"multiply" : "multiply" s * s; diff --git a/tsc/testdata/baselines/reference/conformance/symbolType6.types b/tsc/testdata/baselines/reference/conformance/symbolType6.types index 5010072293994..6176251c5626e 100644 --- a/tsc/testdata/baselines/reference/conformance/symbolType6.types +++ b/tsc/testdata/baselines/reference/conformance/symbolType6.types @@ -3,10 +3,10 @@ === symbolType6.ts === var s = Symbol.for("add"); >s : symbol ->Symbol.for("add") : symbol ->Symbol.for : (key: string) => symbol +>Symbol.for("add") : RegisteredSymbol<"add"> +>Symbol.for : (key: Key) => RegisteredSymbol >Symbol : SymbolConstructor ->for : (key: string) => symbol +>for : (key: Key) => RegisteredSymbol >"add" : "add" var a: any; diff --git a/tsc/testdata/baselines/reference/conformance/symbolType7.types b/tsc/testdata/baselines/reference/conformance/symbolType7.types index 5865a8c28fbf6..b98e3c9071d88 100644 --- a/tsc/testdata/baselines/reference/conformance/symbolType7.types +++ b/tsc/testdata/baselines/reference/conformance/symbolType7.types @@ -3,10 +3,10 @@ === symbolType7.ts === var s = Symbol.for("shift"); >s : symbol ->Symbol.for("shift") : symbol ->Symbol.for : (key: string) => symbol +>Symbol.for("shift") : RegisteredSymbol<"shift"> +>Symbol.for : (key: Key) => RegisteredSymbol >Symbol : SymbolConstructor ->for : (key: string) => symbol +>for : (key: Key) => RegisteredSymbol >"shift" : "shift" s << s; diff --git a/tsc/testdata/baselines/reference/conformance/symbolType8.types b/tsc/testdata/baselines/reference/conformance/symbolType8.types index 148e8699636c2..2178d5e63b0cf 100644 --- a/tsc/testdata/baselines/reference/conformance/symbolType8.types +++ b/tsc/testdata/baselines/reference/conformance/symbolType8.types @@ -3,10 +3,10 @@ === symbolType8.ts === var s = Symbol.for("compare"); >s : symbol ->Symbol.for("compare") : symbol ->Symbol.for : (key: string) => symbol +>Symbol.for("compare") : RegisteredSymbol<"compare"> +>Symbol.for : (key: Key) => RegisteredSymbol >Symbol : SymbolConstructor ->for : (key: string) => symbol +>for : (key: Key) => RegisteredSymbol >"compare" : "compare" s < s; diff --git a/tsc/testdata/baselines/reference/conformance/symbolType9.types b/tsc/testdata/baselines/reference/conformance/symbolType9.types index 7e2b06a1c5d02..39308803347ba 100644 --- a/tsc/testdata/baselines/reference/conformance/symbolType9.types +++ b/tsc/testdata/baselines/reference/conformance/symbolType9.types @@ -3,10 +3,10 @@ === symbolType9.ts === var s = Symbol.for("equal"); >s : symbol ->Symbol.for("equal") : symbol ->Symbol.for : (key: string) => symbol +>Symbol.for("equal") : RegisteredSymbol<"equal"> +>Symbol.for : (key: Key) => RegisteredSymbol >Symbol : SymbolConstructor ->for : (key: string) => symbol +>for : (key: Key) => RegisteredSymbol >"equal" : "equal" s == s; diff --git a/tsc/testdata/baselines/reference/conformance/uniqueSymbols.types b/tsc/testdata/baselines/reference/conformance/uniqueSymbols.types index 1478ffc517f2a..5d5a22b6de7fc 100644 --- a/tsc/testdata/baselines/reference/conformance/uniqueSymbols.types +++ b/tsc/testdata/baselines/reference/conformance/uniqueSymbols.types @@ -29,7 +29,7 @@ const constTypeAndCall: unique symbol = Symbol(); // declaration from initializer const constInitToConstCall = constCall; ->constInitToConstCall : symbol +>constInitToConstCall : unique symbol >constCall : unique symbol const constInitToLetCall = letCall; @@ -41,7 +41,7 @@ const constInitToVarCall = varCall; >varCall : symbol const constInitToConstDeclAmbient = constType; ->constInitToConstDeclAmbient : symbol +>constInitToConstDeclAmbient : unique symbol >constType : unique symbol let letInitToConstCall = constCall; @@ -201,19 +201,19 @@ declare const c: C; >c : C const constInitToCReadonlyStaticCall = C.readonlyStaticCall; ->constInitToCReadonlyStaticCall : symbol +>constInitToCReadonlyStaticCall : unique symbol >C.readonlyStaticCall : unique symbol >C : typeof C >readonlyStaticCall : unique symbol const constInitToCReadonlyStaticType = C.readonlyStaticType; ->constInitToCReadonlyStaticType : symbol +>constInitToCReadonlyStaticType : unique symbol >C.readonlyStaticType : unique symbol >C : typeof C >readonlyStaticType : unique symbol const constInitToCReadonlyStaticTypeAndCall = C.readonlyStaticTypeAndCall; ->constInitToCReadonlyStaticTypeAndCall : symbol +>constInitToCReadonlyStaticTypeAndCall : unique symbol >C.readonlyStaticTypeAndCall : unique symbol >C : typeof C >readonlyStaticTypeAndCall : unique symbol @@ -311,7 +311,7 @@ declare const i: I; >i : I const constInitToIReadonlyType = i.readonlyType; ->constInitToIReadonlyType : symbol +>constInitToIReadonlyType : unique symbol >i.readonlyType : unique symbol >i : I >readonlyType : unique symbol @@ -349,13 +349,13 @@ declare const l: L; >l : L const constInitToLReadonlyType = l.readonlyType; ->constInitToLReadonlyType : symbol +>constInitToLReadonlyType : unique symbol >l.readonlyType : unique symbol >l : L >readonlyType : unique symbol const constInitToLReadonlyNestedType = l.nested.readonlyNestedType; ->constInitToLReadonlyNestedType : symbol +>constInitToLReadonlyNestedType : unique symbol >l.nested.readonlyNestedType : unique symbol >l.nested : { readonly readonlyNestedType: unique symbol; } >l : L @@ -536,17 +536,17 @@ class C0 { >C0 : C0 static readonly a = s; ->a : symbol +>a : unique symbol >s : unique symbol static readonly b = N.s; ->b : symbol +>b : unique symbol >N.s : unique symbol >N : typeof N >s : unique symbol static readonly c = N["s"]; ->c : symbol +>c : unique symbol >N["s"] : unique symbol >N : typeof N >"s" : "s" @@ -568,17 +568,17 @@ class C0 { >"s" : "s" readonly a = s; ->a : symbol +>a : unique symbol >s : unique symbol readonly b = N.s; ->b : symbol +>b : unique symbol >N.s : unique symbol >N : typeof N >s : unique symbol readonly c = N["s"]; ->c : symbol +>c : unique symbol >N["s"] : unique symbol >N : typeof N >"s" : "s" diff --git a/tsc/testdata/baselines/reference/conformance/uniqueSymbolsPropertyNames.errors.txt b/tsc/testdata/baselines/reference/conformance/uniqueSymbolsPropertyNames.errors.txt index 9c200fee5b475..dbf1dda62238a 100644 --- a/tsc/testdata/baselines/reference/conformance/uniqueSymbolsPropertyNames.errors.txt +++ b/tsc/testdata/baselines/reference/conformance/uniqueSymbolsPropertyNames.errors.txt @@ -1,13 +1,17 @@ +uniqueSymbolsPropertyNames.ts(21,21): error TS2352: Conversion of type '{ equal: RegisteredSymbol<"equal">; }' to type 'OpTypes' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first. + Types of property 'equal' are incompatible. + Type 'RegisteredSymbol<"equal">' is not comparable to type 'unique symbol'. uniqueSymbolsPropertyNames.ts(27,3): error TS1117: An object literal cannot have multiple properties with the same name. uniqueSymbolsPropertyNames.ts(28,3): error TS1117: An object literal cannot have multiple properties with the same name. uniqueSymbolsPropertyNames.ts(33,3): error TS1117: An object literal cannot have multiple properties with the same name. uniqueSymbolsPropertyNames.ts(38,3): error TS1117: An object literal cannot have multiple properties with the same name. uniqueSymbolsPropertyNames.ts(43,3): error TS1117: An object literal cannot have multiple properties with the same name. +uniqueSymbolsPropertyNames.ts(44,3): error TS1117: An object literal cannot have multiple properties with the same name. uniqueSymbolsPropertyNames.ts(45,3): error TS1117: An object literal cannot have multiple properties with the same name. uniqueSymbolsPropertyNames.ts(49,3): error TS2300: Duplicate identifier '[uniqueSymbol0]'. uniqueSymbolsPropertyNames.ts(50,3): error TS2300: Duplicate identifier '[uniqueSymbol0]'. -uniqueSymbolsPropertyNames.ts(51,3): error TS2300: Duplicate identifier '[uniqueSymbol1]'. -uniqueSymbolsPropertyNames.ts(52,3): error TS2300: Duplicate identifier '[uniqueSymbol1]'. +uniqueSymbolsPropertyNames.ts(51,3): error TS2300: Duplicate identifier '[uniqueSymbol0]'. +uniqueSymbolsPropertyNames.ts(52,3): error TS2300: Duplicate identifier '[uniqueSymbol0]'. uniqueSymbolsPropertyNames.ts(56,3): error TS2300: Duplicate identifier '[OpNamespace.equal]'. uniqueSymbolsPropertyNames.ts(57,3): error TS2300: Duplicate identifier '[OpNamespace.equal]'. uniqueSymbolsPropertyNames.ts(61,3): error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type. @@ -16,7 +20,7 @@ uniqueSymbolsPropertyNames.ts(63,3): error TS1166: A computed property name in a uniqueSymbolsPropertyNames.ts(64,3): error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type. -==== uniqueSymbolsPropertyNames.ts (16 errors) ==== +==== uniqueSymbolsPropertyNames.ts (18 errors) ==== interface OpTypes { readonly equal: unique symbol; } @@ -38,8 +42,14 @@ uniqueSymbolsPropertyNames.ts(64,3): error TS1166: A computed property name in a } const Op: OpTypes = { + ~ equal: Symbol.for("equal"), + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } as OpTypes; + ~~~~~~~~~~~~ +!!! error TS2352: Conversion of type '{ equal: RegisteredSymbol<"equal">; }' to type 'OpTypes' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first. +!!! error TS2352: Types of property 'equal' are incompatible. +!!! error TS2352: Type 'RegisteredSymbol<"equal">' is not comparable to type 'unique symbol'. const t0 = { equal: "first", @@ -71,6 +81,8 @@ uniqueSymbolsPropertyNames.ts(64,3): error TS1166: A computed property name in a ~~~~~~~~~~~~~~~~~~~~ !!! error TS1117: An object literal cannot have multiple properties with the same name. [getUniqueSymbol1()]: "first", + ~~~~~~~~~~~~~~~~~~~~ +!!! error TS1117: An object literal cannot have multiple properties with the same name. [getUniqueSymbol1()]: "last", ~~~~~~~~~~~~~~~~~~~~ !!! error TS1117: An object literal cannot have multiple properties with the same name. @@ -85,10 +97,10 @@ uniqueSymbolsPropertyNames.ts(64,3): error TS1166: A computed property name in a !!! error TS2300: Duplicate identifier '[uniqueSymbol0]'. [uniqueSymbol1] = "first"; ~~~~~~~~~~~~~~~ -!!! error TS2300: Duplicate identifier '[uniqueSymbol1]'. +!!! error TS2300: Duplicate identifier '[uniqueSymbol0]'. [uniqueSymbol1] = "last"; ~~~~~~~~~~~~~~~ -!!! error TS2300: Duplicate identifier '[uniqueSymbol1]'. +!!! error TS2300: Duplicate identifier '[uniqueSymbol0]'. } class Cls2 { diff --git a/tsc/testdata/baselines/reference/conformance/uniqueSymbolsPropertyNames.symbols b/tsc/testdata/baselines/reference/conformance/uniqueSymbolsPropertyNames.symbols index 05372d8887654..d2395ecd0d3b1 100644 --- a/tsc/testdata/baselines/reference/conformance/uniqueSymbolsPropertyNames.symbols +++ b/tsc/testdata/baselines/reference/conformance/uniqueSymbolsPropertyNames.symbols @@ -131,19 +131,19 @@ class Cls1 { >Cls1 : Symbol(Cls1, Decl(uniqueSymbolsPropertyNames.ts, 45, 2)) [uniqueSymbol0] = "first"; ->[uniqueSymbol0] : Symbol(Cls1[uniqueSymbol0], Decl(uniqueSymbolsPropertyNames.ts, 47, 12), Decl(uniqueSymbolsPropertyNames.ts, 48, 28)) +>[uniqueSymbol0] : Symbol(Cls1[uniqueSymbol0], Decl(uniqueSymbolsPropertyNames.ts, 47, 12), Decl(uniqueSymbolsPropertyNames.ts, 48, 28), Decl(uniqueSymbolsPropertyNames.ts, 49, 27), Decl(uniqueSymbolsPropertyNames.ts, 50, 28)) >uniqueSymbol0 : Symbol(uniqueSymbol0, Decl(uniqueSymbolsPropertyNames.ts, 8, 5)) [uniqueSymbol0] = "last"; ->[uniqueSymbol0] : Symbol(Cls1[uniqueSymbol0], Decl(uniqueSymbolsPropertyNames.ts, 47, 12), Decl(uniqueSymbolsPropertyNames.ts, 48, 28)) +>[uniqueSymbol0] : Symbol(Cls1[uniqueSymbol0], Decl(uniqueSymbolsPropertyNames.ts, 47, 12), Decl(uniqueSymbolsPropertyNames.ts, 48, 28), Decl(uniqueSymbolsPropertyNames.ts, 49, 27), Decl(uniqueSymbolsPropertyNames.ts, 50, 28)) >uniqueSymbol0 : Symbol(uniqueSymbol0, Decl(uniqueSymbolsPropertyNames.ts, 8, 5)) [uniqueSymbol1] = "first"; ->[uniqueSymbol1] : Symbol(Cls1[uniqueSymbol1], Decl(uniqueSymbolsPropertyNames.ts, 49, 27), Decl(uniqueSymbolsPropertyNames.ts, 50, 28)) +>[uniqueSymbol1] : Symbol(Cls1[uniqueSymbol0], Decl(uniqueSymbolsPropertyNames.ts, 47, 12), Decl(uniqueSymbolsPropertyNames.ts, 48, 28), Decl(uniqueSymbolsPropertyNames.ts, 49, 27), Decl(uniqueSymbolsPropertyNames.ts, 50, 28)) >uniqueSymbol1 : Symbol(uniqueSymbol1, Decl(uniqueSymbolsPropertyNames.ts, 9, 5)) [uniqueSymbol1] = "last"; ->[uniqueSymbol1] : Symbol(Cls1[uniqueSymbol1], Decl(uniqueSymbolsPropertyNames.ts, 49, 27), Decl(uniqueSymbolsPropertyNames.ts, 50, 28)) +>[uniqueSymbol1] : Symbol(Cls1[uniqueSymbol0], Decl(uniqueSymbolsPropertyNames.ts, 47, 12), Decl(uniqueSymbolsPropertyNames.ts, 48, 28), Decl(uniqueSymbolsPropertyNames.ts, 49, 27), Decl(uniqueSymbolsPropertyNames.ts, 50, 28)) >uniqueSymbol1 : Symbol(uniqueSymbol1, Decl(uniqueSymbolsPropertyNames.ts, 9, 5)) } From 34571279083fae3d2750ca4cf25e2e574dce8804 Mon Sep 17 00:00:00 2001 From: Michael FIG Date: Fri, 2 Oct 2026 23:43:10 -0600 Subject: [PATCH 10/11] Emit inferred registered symbol keys as mapped properties Serialize computed expressions through their known registered-symbol types, preserving ordinary and readonly properties. Add declaration emit coverage and accept the corrected symbol-name baseline. Co-authored-by: Codex --- tsc/internal/checker/nodebuilderimpl.go | 48 ++++++++++++-- ...registeredSymbolComputedNameDeclaration.js | 39 ++++++++++++ ...teredSymbolComputedNameDeclaration.symbols | 38 ++++++++++++ ...isteredSymbolComputedNameDeclaration.types | 50 +++++++++++++++ .../uniqueSymbolsPropertyNames.types | 62 +++++++++---------- ...registeredSymbolComputedNameDeclaration.ts | 13 ++++ 6 files changed, 215 insertions(+), 35 deletions(-) create mode 100644 tsc/testdata/baselines/reference/compiler/registeredSymbolComputedNameDeclaration.js create mode 100644 tsc/testdata/baselines/reference/compiler/registeredSymbolComputedNameDeclaration.symbols create mode 100644 tsc/testdata/baselines/reference/compiler/registeredSymbolComputedNameDeclaration.types create mode 100644 tsc/testdata/tests/cases/compiler/registeredSymbolComputedNameDeclaration.ts diff --git a/tsc/internal/checker/nodebuilderimpl.go b/tsc/internal/checker/nodebuilderimpl.go index 289b2ba52a754..f884a08b09ced 100644 --- a/tsc/internal/checker/nodebuilderimpl.go +++ b/tsc/internal/checker/nodebuilderimpl.go @@ -2844,12 +2844,52 @@ func (b *NodeBuilderImpl) createTypeNodeFromObjectType(t *Type) *ast.TypeNode { restoreFlags := b.saveRestoreFlags() b.ctx.flags |= nodebuilder.FlagsInObjectTypeLiteral + var mappedProperties []*ast.Symbol + var ordinaryProperties []*ast.Symbol + for _, property := range resolved.properties { + var nameType *Type + if b.ch.valueSymbolLinks.Has(property) { + nameType = b.ch.valueSymbolLinks.TryGet(property).nameType + } + name := ast.GetNameOfDeclaration(property.ValueDeclaration) + if nameType != nil && nameType.flags&TypeFlagsUniqueESSymbol != 0 && isRegisteredSymbolAlias(nameType.alias) && + name != nil && ast.IsComputedPropertyName(name) && !ast.IsEntityNameExpression(name.Expression()) { + mappedProperties = append(mappedProperties, property) + } else { + ordinaryProperties = append(ordinaryProperties, property) + } + } + if len(mappedProperties) != 0 { + copy := *resolved + copy.properties = ordinaryProperties + resolved = © + } members := b.createTypeNodesFromResolvedType(resolved) + var typeNodes []*ast.TypeNode + if members != nil && len(members.Nodes) != 0 || len(mappedProperties) == 0 { + typeLiteralNode := b.f.NewTypeLiteralNode(members) + b.ctx.approximateLength += 2 + b.e.SetEmitFlags(typeLiteralNode, core.IfElse((b.ctx.flags&nodebuilder.FlagsMultilineObjectLiterals != 0), 0, printer.EFSingleLine)) + typeNodes = append(typeNodes, typeLiteralNode) + } + for _, property := range mappedProperties { + nameType := b.ch.valueSymbolLinks.Get(property).nameType + key := b.f.NewTypeParameterDeclaration(nil, b.f.NewIdentifier("K"), b.typeToTypeNode(nameType), nil, nil) + var readonlyToken *ast.Node + if b.ch.isReadonlySymbol(property) { + readonlyToken = b.f.NewToken(ast.KindReadonlyKeyword) + } + var questionToken *ast.Node + if property.Flags&ast.SymbolFlagsOptional != 0 { + questionToken = b.f.NewToken(ast.KindQuestionToken) + } + typeNodes = append(typeNodes, b.f.NewMappedTypeNode(readonlyToken, key, nil, questionToken, b.typeToTypeNode(b.ch.getNonMissingTypeOfSymbol(property)), nil)) + } restoreFlags() - typeLiteralNode := b.f.NewTypeLiteralNode(members) - b.ctx.approximateLength += 2 - b.e.SetEmitFlags(typeLiteralNode, core.IfElse((b.ctx.flags&nodebuilder.FlagsMultilineObjectLiterals != 0), 0, printer.EFSingleLine)) - return typeLiteralNode + if len(typeNodes) == 1 { + return typeNodes[0] + } + return b.f.NewIntersectionTypeNode(b.f.NewNodeList(typeNodes)) } func getTypeAliasForTypeLiteral(c *Checker, t *Type) *ast.Symbol { diff --git a/tsc/testdata/baselines/reference/compiler/registeredSymbolComputedNameDeclaration.js b/tsc/testdata/baselines/reference/compiler/registeredSymbolComputedNameDeclaration.js new file mode 100644 index 0000000000000..bc1d488b54574 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/registeredSymbolComputedNameDeclaration.js @@ -0,0 +1,39 @@ +//// [tests/cases/compiler/registeredSymbolComputedNameDeclaration.ts] //// + +//// [registeredSymbolComputedNameDeclaration.ts] +export const key = Symbol.for("abc"); +export function getKey(): typeof key { return key; } + +export const value = { + ordinary: 1, + [getKey()]: "text", + [Symbol.for("other")]: true, +}; + +export const readonlyValue = { [getKey()]: "fixed" } as const; + + +//// [registeredSymbolComputedNameDeclaration.js] +export const key = Symbol.for("abc"); +export function getKey() { return key; } +export const value = { + ordinary: 1, + [getKey()]: "text", + [Symbol.for("other")]: true, +}; +export const readonlyValue = { [getKey()]: "fixed" }; + + +//// [registeredSymbolComputedNameDeclaration.d.ts] +export declare const key: RegisteredSymbol<"abc">; +export declare function getKey(): typeof key; +export declare const value: { + ordinary: number; +} & { + [K in RegisteredSymbol<"abc">]: string; +} & { + [K in RegisteredSymbol<"other">]: boolean; +}; +export declare const readonlyValue: { + readonly [K in RegisteredSymbol<"abc">]: "fixed"; +}; diff --git a/tsc/testdata/baselines/reference/compiler/registeredSymbolComputedNameDeclaration.symbols b/tsc/testdata/baselines/reference/compiler/registeredSymbolComputedNameDeclaration.symbols new file mode 100644 index 0000000000000..a78d3938910ab --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/registeredSymbolComputedNameDeclaration.symbols @@ -0,0 +1,38 @@ +//// [tests/cases/compiler/registeredSymbolComputedNameDeclaration.ts] //// + +=== registeredSymbolComputedNameDeclaration.ts === +export const key = Symbol.for("abc"); +>key : Symbol(key, Decl(registeredSymbolComputedNameDeclaration.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 function getKey(): typeof key { return key; } +>getKey : Symbol(getKey, Decl(registeredSymbolComputedNameDeclaration.ts, 0, 37)) +>key : Symbol(key, Decl(registeredSymbolComputedNameDeclaration.ts, 0, 12)) +>key : Symbol(key, Decl(registeredSymbolComputedNameDeclaration.ts, 0, 12)) + +export const value = { +>value : Symbol(value, Decl(registeredSymbolComputedNameDeclaration.ts, 3, 12)) + + ordinary: 1, +>ordinary : Symbol(ordinary, Decl(registeredSymbolComputedNameDeclaration.ts, 3, 22)) + + [getKey()]: "text", +>[getKey()] : Symbol([getKey()], Decl(registeredSymbolComputedNameDeclaration.ts, 4, 16)) +>getKey : Symbol(getKey, Decl(registeredSymbolComputedNameDeclaration.ts, 0, 37)) + + [Symbol.for("other")]: true, +>[Symbol.for("other")] : Symbol([Symbol.for("other")], Decl(registeredSymbolComputedNameDeclaration.ts, 5, 23)) +>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 readonlyValue = { [getKey()]: "fixed" } as const; +>readonlyValue : Symbol(readonlyValue, Decl(registeredSymbolComputedNameDeclaration.ts, 9, 12)) +>[getKey()] : Symbol([getKey()], Decl(registeredSymbolComputedNameDeclaration.ts, 9, 30)) +>getKey : Symbol(getKey, Decl(registeredSymbolComputedNameDeclaration.ts, 0, 37)) +>const : Symbol(const) + diff --git a/tsc/testdata/baselines/reference/compiler/registeredSymbolComputedNameDeclaration.types b/tsc/testdata/baselines/reference/compiler/registeredSymbolComputedNameDeclaration.types new file mode 100644 index 0000000000000..a3de8a2fe5995 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/registeredSymbolComputedNameDeclaration.types @@ -0,0 +1,50 @@ +//// [tests/cases/compiler/registeredSymbolComputedNameDeclaration.ts] //// + +=== registeredSymbolComputedNameDeclaration.ts === +export const key = Symbol.for("abc"); +>key : RegisteredSymbol<"abc"> +>Symbol.for("abc") : RegisteredSymbol<"abc"> +>Symbol.for : (key: Key) => RegisteredSymbol +>Symbol : SymbolConstructor +>for : (key: Key) => RegisteredSymbol +>"abc" : "abc" + +export function getKey(): typeof key { return key; } +>getKey : () => typeof key +>key : RegisteredSymbol<"abc"> +>key : RegisteredSymbol<"abc"> + +export const value = { +>value : { ordinary: number; } & { [K in RegisteredSymbol<"abc">]: string;} & { [K in RegisteredSymbol<"other">]: boolean;} +>{ ordinary: 1, [getKey()]: "text", [Symbol.for("other")]: true,} : { ordinary: number; } & { [K in RegisteredSymbol<"abc">]: string;} & { [K in RegisteredSymbol<"other">]: boolean;} + + ordinary: 1, +>ordinary : number +>1 : 1 + + [getKey()]: "text", +>[getKey()] : string +>getKey() : RegisteredSymbol<"abc"> +>getKey : () => typeof key +>"text" : "text" + + [Symbol.for("other")]: true, +>[Symbol.for("other")] : boolean +>Symbol.for("other") : RegisteredSymbol<"other"> +>Symbol.for : (key: Key) => RegisteredSymbol +>Symbol : SymbolConstructor +>for : (key: Key) => RegisteredSymbol +>"other" : "other" +>true : true + +}; + +export const readonlyValue = { [getKey()]: "fixed" } as const; +>readonlyValue : { readonly [K in RegisteredSymbol<"abc">]: "fixed";} +>{ [getKey()]: "fixed" } as const : { readonly [K in RegisteredSymbol<"abc">]: "fixed";} +>{ [getKey()]: "fixed" } : { readonly [K in RegisteredSymbol<"abc">]: "fixed";} +>[getKey()] : "fixed" +>getKey() : RegisteredSymbol<"abc"> +>getKey : () => typeof key +>"fixed" : "fixed" + diff --git a/tsc/testdata/baselines/reference/conformance/uniqueSymbolsPropertyNames.types b/tsc/testdata/baselines/reference/conformance/uniqueSymbolsPropertyNames.types index f3596c9f4fda0..1e452fc50db00 100644 --- a/tsc/testdata/baselines/reference/conformance/uniqueSymbolsPropertyNames.types +++ b/tsc/testdata/baselines/reference/conformance/uniqueSymbolsPropertyNames.types @@ -14,49 +14,49 @@ namespace OpNamespace { } const uniqueSymbol0 = Symbol.for(""); ->uniqueSymbol0 : unique symbol ->Symbol.for("") : unique symbol ->Symbol.for : (key: string) => symbol +>uniqueSymbol0 : RegisteredSymbol<""> +>Symbol.for("") : RegisteredSymbol<""> +>Symbol.for : (key: Key) => RegisteredSymbol >Symbol : SymbolConstructor ->for : (key: string) => symbol +>for : (key: Key) => RegisteredSymbol >"" : "" const uniqueSymbol1 = Symbol.for(""); ->uniqueSymbol1 : unique symbol ->Symbol.for("") : unique symbol ->Symbol.for : (key: string) => symbol +>uniqueSymbol1 : RegisteredSymbol<""> +>Symbol.for("") : RegisteredSymbol<""> +>Symbol.for : (key: Key) => RegisteredSymbol >Symbol : SymbolConstructor ->for : (key: string) => symbol +>for : (key: Key) => RegisteredSymbol >"" : "" function getUniqueSymbol0(): typeof uniqueSymbol0 { >getUniqueSymbol0 : () => typeof uniqueSymbol0 ->uniqueSymbol0 : unique symbol +>uniqueSymbol0 : RegisteredSymbol<""> return uniqueSymbol0; ->uniqueSymbol0 : unique symbol +>uniqueSymbol0 : RegisteredSymbol<""> } function getUniqueSymbol1(): typeof uniqueSymbol1 { >getUniqueSymbol1 : () => typeof uniqueSymbol1 ->uniqueSymbol1 : unique symbol +>uniqueSymbol1 : RegisteredSymbol<""> return uniqueSymbol1; ->uniqueSymbol1 : unique symbol +>uniqueSymbol1 : RegisteredSymbol<""> } const Op: OpTypes = { >Op : OpTypes >{ equal: Symbol.for("equal"),} as OpTypes : OpTypes ->{ equal: Symbol.for("equal"),} : { equal: symbol; } +>{ equal: Symbol.for("equal"),} : { equal: RegisteredSymbol<"equal">; } equal: Symbol.for("equal"), ->equal : symbol ->Symbol.for("equal") : symbol ->Symbol.for : (key: string) => symbol +>equal : RegisteredSymbol<"equal"> +>Symbol.for("equal") : RegisteredSymbol<"equal"> +>Symbol.for : (key: Key) => RegisteredSymbol >Symbol : SymbolConstructor ->for : (key: string) => symbol +>for : (key: Key) => RegisteredSymbol >"equal" : "equal" } as OpTypes; @@ -121,30 +121,30 @@ const t2 = { }; const t3 = { ->t3 : { [uniqueSymbol0]: string; [uniqueSymbol1]: string; } ->{ [getUniqueSymbol0()]: "first", [getUniqueSymbol0()]: "last", [getUniqueSymbol1()]: "first", [getUniqueSymbol1()]: "last",} : { [uniqueSymbol0]: string; [uniqueSymbol1]: string; } +>t3 : { [K in RegisteredSymbol<"">]: string;} +>{ [getUniqueSymbol0()]: "first", [getUniqueSymbol0()]: "last", [getUniqueSymbol1()]: "first", [getUniqueSymbol1()]: "last",} : { [K in RegisteredSymbol<"">]: string;} [getUniqueSymbol0()]: "first", >[getUniqueSymbol0()] : string ->getUniqueSymbol0() : unique symbol +>getUniqueSymbol0() : RegisteredSymbol<""> >getUniqueSymbol0 : () => typeof uniqueSymbol0 >"first" : "first" [getUniqueSymbol0()]: "last", >[getUniqueSymbol0()] : string ->getUniqueSymbol0() : unique symbol +>getUniqueSymbol0() : RegisteredSymbol<""> >getUniqueSymbol0 : () => typeof uniqueSymbol0 >"last" : "last" [getUniqueSymbol1()]: "first", >[getUniqueSymbol1()] : string ->getUniqueSymbol1() : unique symbol +>getUniqueSymbol1() : RegisteredSymbol<""> >getUniqueSymbol1 : () => typeof uniqueSymbol1 >"first" : "first" [getUniqueSymbol1()]: "last", >[getUniqueSymbol1()] : string ->getUniqueSymbol1() : unique symbol +>getUniqueSymbol1() : RegisteredSymbol<""> >getUniqueSymbol1 : () => typeof uniqueSymbol1 >"last" : "last" @@ -155,22 +155,22 @@ class Cls1 { [uniqueSymbol0] = "first"; >[uniqueSymbol0] : string ->uniqueSymbol0 : unique symbol +>uniqueSymbol0 : RegisteredSymbol<""> >"first" : "first" [uniqueSymbol0] = "last"; >[uniqueSymbol0] : string ->uniqueSymbol0 : unique symbol +>uniqueSymbol0 : RegisteredSymbol<""> >"last" : "last" [uniqueSymbol1] = "first"; >[uniqueSymbol1] : string ->uniqueSymbol1 : unique symbol +>uniqueSymbol1 : RegisteredSymbol<""> >"first" : "first" [uniqueSymbol1] = "last"; >[uniqueSymbol1] : string ->uniqueSymbol1 : unique symbol +>uniqueSymbol1 : RegisteredSymbol<""> >"last" : "last" } @@ -197,25 +197,25 @@ class Cls3 { [getUniqueSymbol0()] = "first"; >[getUniqueSymbol0()] : string ->getUniqueSymbol0() : unique symbol +>getUniqueSymbol0() : RegisteredSymbol<""> >getUniqueSymbol0 : () => typeof uniqueSymbol0 >"first" : "first" [getUniqueSymbol0()] = "last"; >[getUniqueSymbol0()] : string ->getUniqueSymbol0() : unique symbol +>getUniqueSymbol0() : RegisteredSymbol<""> >getUniqueSymbol0 : () => typeof uniqueSymbol0 >"last" : "last" [getUniqueSymbol1()] = "first"; >[getUniqueSymbol1()] : string ->getUniqueSymbol1() : unique symbol +>getUniqueSymbol1() : RegisteredSymbol<""> >getUniqueSymbol1 : () => typeof uniqueSymbol1 >"first" : "first" [getUniqueSymbol1()] = "last"; >[getUniqueSymbol1()] : string ->getUniqueSymbol1() : unique symbol +>getUniqueSymbol1() : RegisteredSymbol<""> >getUniqueSymbol1 : () => typeof uniqueSymbol1 >"last" : "last" } diff --git a/tsc/testdata/tests/cases/compiler/registeredSymbolComputedNameDeclaration.ts b/tsc/testdata/tests/cases/compiler/registeredSymbolComputedNameDeclaration.ts new file mode 100644 index 0000000000000..563aaf1dadeb0 --- /dev/null +++ b/tsc/testdata/tests/cases/compiler/registeredSymbolComputedNameDeclaration.ts @@ -0,0 +1,13 @@ +// @target: es2015 +// @declaration: true + +export const key = Symbol.for("abc"); +export function getKey(): typeof key { return key; } + +export const value = { + ordinary: 1, + [getKey()]: "text", + [Symbol.for("other")]: true, +}; + +export const readonlyValue = { [getKey()]: "fixed" } as const; From 10d6b071ebf2d5606d253741be20ac3a3666e071 Mon Sep 17 00:00:00 2001 From: Michael FIG Date: Sat, 3 Oct 2026 11:18:45 -0600 Subject: [PATCH 11/11] Simplify registered symbol type flag masks Use the existing Instantiable aggregate for base constraints and omit a redundant IncludesMask bit in both enum definitions. Co-authored-by: Codex --- packages/typescript/src/enums/typeFlags.enum.ts | 2 +- tsc/internal/checker/checker.go | 2 +- tsc/internal/checker/types.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/typescript/src/enums/typeFlags.enum.ts b/packages/typescript/src/enums/typeFlags.enum.ts index 1621428605319..ead524eb1eb51 100644 --- a/packages/typescript/src/enums/typeFlags.enum.ts +++ b/packages/typescript/src/enums/typeFlags.enum.ts @@ -65,7 +65,7 @@ export enum TypeFlags { 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 | ESSymbolLike | NonPrimitive, - IncludesMask = Any | Unknown | Primitive | Never | Object | Union | Intersection | NonPrimitive | TemplateLiteral | StringMapping | RegisteredESSymbol, + IncludesMask = Any | Unknown | Primitive | Never | Object | Union | Intersection | NonPrimitive | TemplateLiteral | StringMapping, IncludesMissingType = TypeParameter, IncludesNonWideningType = Index, IncludesWildcard = IndexedAccess, diff --git a/tsc/internal/checker/checker.go b/tsc/internal/checker/checker.go index 6457d663421a2..90ba7825238a7 100644 --- a/tsc/internal/checker/checker.go +++ b/tsc/internal/checker/checker.go @@ -27919,7 +27919,7 @@ func (c *Checker) getBaseConstraintOrType(t *Type) *Type { } func (c *Checker) getBaseConstraintOfType(t *Type) *Type { - if t.flags&(TypeFlagsInstantiableNonPrimitive|TypeFlagsUnionOrIntersection|TypeFlagsTemplateLiteral|TypeFlagsStringMapping|TypeFlagsRegisteredESSymbol|TypeFlagsIndex) != 0 || c.isGenericTupleType(t) { + if t.flags&(TypeFlagsInstantiable|TypeFlagsUnionOrIntersection) != 0 || c.isGenericTupleType(t) { constraint := c.getResolvedBaseConstraint(t, nil) if constraint != c.noConstraintType && constraint != c.circularConstraintType { return constraint diff --git a/tsc/internal/checker/types.go b/tsc/internal/checker/types.go index 7c97e48a64e80..7d1f56f320b9d 100644 --- a/tsc/internal/checker/types.go +++ b/tsc/internal/checker/types.go @@ -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 | TypeFlagsESSymbolLike | TypeFlagsNonPrimitive // The following flags are aggregated during union and intersection type construction - TypeFlagsIncludesMask = TypeFlagsAny | TypeFlagsUnknown | TypeFlagsPrimitive | TypeFlagsNever | TypeFlagsObject | TypeFlagsUnion | TypeFlagsIntersection | TypeFlagsNonPrimitive | TypeFlagsTemplateLiteral | TypeFlagsStringMapping | TypeFlagsRegisteredESSymbol + TypeFlagsIncludesMask = TypeFlagsAny | TypeFlagsUnknown | TypeFlagsPrimitive | TypeFlagsNever | TypeFlagsObject | TypeFlagsUnion | TypeFlagsIntersection | TypeFlagsNonPrimitive | TypeFlagsTemplateLiteral | TypeFlagsStringMapping // The following flags are used for different purposes during union and intersection type construction TypeFlagsIncludesMissingType = TypeFlagsTypeParameter TypeFlagsIncludesNonWideningType = TypeFlagsIndex