由于MDN说,我正尝试将symbol作为键类型来定义对象。
符号值可以用作对象属性的标识符[...]
但是将其用作键属性的类型:
type obj = {
[key: symbol | string]: string
}
导致以下错误:
TS1023:索引签名参数类型必须为“字符串”或“数字”。
即使它也可以用作索引类型。
我正在使用最新的打字稿版本(v3.7.2
),发现了相关的问题:
symbol
)我也看过typescript symbol docs,但它们仅显示了如何将其用作值而不是类型。
示例:
const obj = {} as {
[key: number | symbol]: string // Won't work
};
const sym = Symbol('My symbol');
obj[sym] = 'Hi';
答案 0 :(得分:2)
不幸的是,目前在TypeScript中这是不可能的。如果您必须与某些希望使用此符号或确实希望使用符号作为键的API进行互操作,则可以使用以下笨拙的版本:
// 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
答案 1 :(得分:1)
机会很好,symbols和index signatures中的其他键类型将是implemented和TypeScript 4.2(请参阅Pull Request)。
您可以在staging Playground中测试该功能:
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"]
目前,SymbolIndex
会trigger an error:
索引签名参数类型必须为“字符串”或“数字”。(1023)
话虽如此,如果您只想要一个带有符号且没有索引签名的对象类型,那么您今天就可以这样做(Playground):
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