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 string
though 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.20210627
This 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 astring
index signature in the resulting type. Sincesymbol
s can’t have index signatures, it quietly drops them (for now, at least).Hmm. So this code working pre
2.9
is a bug?Shouldn’t you always be able to index a property by
PropertyKey
(by definition)? Given thatPropertyKey
isstring | number | symbol
, I think it should follow that indexing by asymbol
should 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
MyObject
you will find below. One main feature is that the content ofMyObject
can be different depending on thecontent
. To enable users to write something likemyObject.test
I 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.