TypeScript: Type 'symbol' cannot be used as an index type.
TypeScript Version: 3.0.0-dev.20180601
Code
const x: Record<keyof any, string> = {};
x['hello'] = 'world';
const sym: symbol = Symbol('sym');
x[sym] = 'symbol string';
Expected behavior:
No errors. tsc --target es6 symbol-index.ts works with 2.8.4.
Actual behavior:
symbol-index.ts(4,3): error TS2538: Type 'symbol' cannot be used as an index type.
when running tsc --pretty false --target es6 symbol-index.ts with 2.9.1 or next.
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Reactions: 28
- Comments: 16 (4 by maintainers)
Commits related to this issue
- Fall back to TypeScript 2.8, as 2.9 currently generates a raft of spurious error messages. (The problem has been fixed, but doesn't appear to have landed in TS yet.) — committed to elix/elix by JanMiksovsky 6 years ago
- :-((( DIRTY HACK hotfix due to TS not supporting `symbol` as a type in latest npm TS release (3.5.2): see also https://github.com/microsoft/TypeScript/issues/1863 + https://github.com/Microsoft/TypeS... — committed to GerHobbelt/snabbdom by GerHobbelt 5 years ago
@weswigham @mhegazy Do we have any spec that describes that this behavior is intended? For now, the main point that I get from https://github.com/Microsoft/TypeScript/issues/24587#issuecomment-394014604 is that we forbid symbols as indexers because we have no symbol index signatures and for me it’s sounds like bug in compiler because:
According to refs above consider following use case. I am implementing DI container where i would like to provide library users ability to use Symbols as keys(to avoid components collision) for their components. In my code I have something like:
interface ComponentsContainer { [key: PropertyKey]: Component; }Could someone provide strong argumentation why it’s not a bug in compiler and this code shouldn’t work?
Can’t imagine how it could be marked as “work as intended”, since we have this “TypeScript is a typed superset of JavaScript” on main page. This is definitely a bug in a type system and should be fixed somehow.
Automatically closing this issue for housekeeping purposes. The issue labels indicate that it is unactionable at the moment or has already been addressed.
@prshreshtha just write
or if you must type annotate, write
we forbid symbols as indexers because we have no symbol index signatures (this was a hole we patched in 2.9 - previously it would assume the string indexer type, which was very incorrect), however unique symbols - a type associated with exactly one symbol are fine, since they refer to exactly one property.
For the unbearable change, I gotta write a ugly line like:
What a stupid shit…
Can’t believe that shit works.
Had to use
as unknown as stringthough since linter dislikes straight-upany.@mhegazy why you labling it “Working as Intended”? Please answer to the comment
Seems to be fixed by https://github.com/microsoft/TypeScript/pull/44512 !
Available in
4.4.0-dev.20210627This issue seems mislabeled, but the main issue is #1863 and it’s still open (and stalled apparently).
@weswigham both of your suggestions produce
symbol-index.ts(4,3): error TS2538: Type 'unique symbol' cannot be used as an index type.Playground Link: http://www.typescriptlang.org/play/#src=const x%3A Record<keyof any%2C string> %3D {}%3B x[‘hello’] %3D ‘world’%3B const sym %3D Symbol(‘sym’)%3B x[sym] %3D ‘symbol string’%3B const sym2%3A unique symbol %3D Symbol(‘sym’)%3B x[sym2] %3D ‘symbol string’%3B
Conceptually yes - the actual machinery to make it work was never in place - the symbols were just being mistaken for strings.
Yeah, that’s because square bracket accesses to
{}are unchecked:I don’t know how to feel about it, personally, but it’s been “a way out” of the type checker for awhile. Usages are an error under
noImplicitAny, so it doesn’t come up too often.Yeah, since the mapped type maps over
string, it manufactures astringindex signature in the resulting type. Sincesymbols can’t have index signatures, it quietly drops them (for now, at least).Hmm. So this code working pre
2.9is a bug?Shouldn’t you always be able to index a property by
PropertyKey(by definition)? Given thatPropertyKeyisstring | number | symbol, I think it should follow that indexing by asymbolshould always be possible.Oddly enough, the following works:
But this doesn’t:
@weswigham
I have a question which is similar to this issue, I believe.
I author a library containig a similar class like
MyObjectyou will find below. One main feature is that the content ofMyObjectcan be different depending on thecontent. To enable users to write something likemyObject.testI added the property[key: string]: any;to the interface.With typescript 2.9.x this will result in
Type 'unique symbol' cannot be used as an index type.error, but wenn I remove this line users will getProperty 'test' does not exist on type 'MyObject'.when trying to access anything “dynamically added”.Is there any way of doing this properly?
edit: It seems I found a workaround. If i declare the symbol
const sbl: any = Symbol.for('content')typescript will accept it.