Reputation: 2986
I'm trying to define an object with a symbol as key-type since MDN says:
A symbol value may be used as an identifier for object properties [...]
But using it as type for the key-property:
type obj = {
[key: symbol | string]: string
}
results in the following error:
TS1023: An index signature parameter type must be either 'string' or 'number'.
even it can be used as index-type.
I'm using the latest typescript version (v3.7.2
), related questions I've found:
symbol
)I've also took a look at the typescript symbol docs but they only show how it's used as value, not as type.
Example:
const obj = {} as {
[key: number | symbol]: string // Won't work
};
const sym = Symbol('My symbol');
obj[sym] = 'Hi';
Upvotes: 37
Views: 26689
Reputation: 74500
TypeScript 4.4 allows symbols in index signatures:
type SymbolIndex = {
[key: symbol | string]: string // works
}
const sym = Symbol("descr");
const t1: SymbolIndex = {
"foo": "bar",
[Symbol.iterator]: "qux",
sym: "sym"
};
// all result in string
t1.foo
t1.sym
t1[Symbol.iterator]
t1["oh"]
With older versions, SymbolIndex
will trigger an error:
An index signature parameter type must be either 'string' or 'number'.(1023)
If you just want an object type with symbols and no index signature, you can already do that today:
const sym = Symbol() // note const (no let)
type O = {
foo: string
[Symbol.iterator]: string
[sym]: number
}
let o: O = { [sym] : 3, [Symbol.iterator]: "bar", foo: "qux"}
let { [sym]: symVal } = o
Upvotes: 12
Reputation: 2822
Unfortunately this is not possible at the moment in TypeScript. If you have to interoperate with some APIs that expect this or really want to use symbols as keys, you can do this awkward version:
// Ensure we can not pass regular map to our custom functions
type SymbolMapTag = { readonly symbol: unique symbol }
type SymbolMap = SymbolMapTag & {
[Key in string | number | symbol]: string;
}
function set_symbol<T extends SymbolMap, TSym extends symbol>
(target: T, sym: TSym, value: T[TSym]) {
target[sym] = value;
}
function get_symbol<T extends SymbolMap, TSym extends symbol>
(target: T, sym: TSym): T[TSym] {
return target[sym];
}
const symbol_map = {} as SymbolMap;
const sym = Symbol('My symbol');
set_symbol(symbol_map, sym, "hi");
get_symbol(symbol_map, sym); // string
type NonSymbolMap = {
[Key in string | number]: string;
}
const non_symbol_map = {} as NonSymbolMap;
set_symbol(non_symbol_map, sym, "hi"); // error
get_symbol(non_symbol_map, sym); // error
Upvotes: 8