当前位置: 首页 > 知识库问答 >
问题:

在TypeScript中使用符号作为对象键类型

郁明诚
2023-03-14

我正在尝试将一个带有符号的对象定义为键类型,因为 MDN 说:

符号值可用作对象属性的标识符[…]

但是使用它作为键属性的类型:

type obj = {
    [key: symbol | string]: string
}

导致以下错误:

TS1023:索引签名参数类型必须为“字符串”或“数字”。

甚至它也可以用作索引类型。我正在使用最新的打字稿版本(v3.7.2),我发现了相关问题:

  • 类型脚本:以符号为键解构对象(他使用的是符号的实际实例,我想要类型符号
  • TypeScript:当尝试使用字符串|数字
  • 时,索引签名参数必须是“字符串”或“数字”
  • ES6:以符号为键解构对象(这不是解决方案——使用实际实例作为类型似乎有点错误,因为每个符号实例都是唯一的…)

我还看了一下typescript符号文档,但是它们只显示了它是如何作为值使用的,而不是作为类型。

示例

const obj = {} as {
    [key: number | symbol]: string // Won't work
};

const sym = Symbol('My symbol');
obj[sym] = 'Hi';

微软/TypeScript 上的问题

打开功能请求

共有2个答案

符佐
2023-03-14

TypeScript 4.4允许索引签名中的符号:

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会触发错误:

索引签名参数类型必须是“字符串”或“数字”。(1023)

如果您只需要一个带有符号且没有索引签名的对象类型,您今天已经可以这样做了:

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

操场

斜单鹗
2023-03-14

不幸的是,目前在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
 类似资料:
  • 我在TypeScript中有一个接口或抽象类,我有一大堆实现/扩展接口/类的类,我想用所有子类的构造函数生成一个数组,但我想把数组类型为接口/超类。这可能吗? 可以将键入以外的任何内容吗?我想尽可能地说得具体些。我知道在ActionScript中您至少可以执行,在Haxe中您可以执行,但是在TypeScript中您甚至不能作为afaik键入。

  • React/Typescript中对象的类型是什么,例如: 如果我需要将它定义为一个对象,我应该输入什么类型,而不是

  • 如果我有: 如何在myKey上访问myObj?

  • 我希望将变量插入到对象键结构中,但我只得到变量名,而不是变量值。

  • 问题内容: 为什么下面的工作? 而这不起作用: 更清楚地说:目前,我无法将CSS属性作为变量传递给animate函数。 问题答案: 是有效的对象文字。该代码将创建一个对象,其属性名为,值为10。以下两项相同: 在ES5及更早版本中,不能在对象文字中使用变量作为属性名称。您唯一的选择是执行以下操作: ES6 将 _ComputedPropertyName_定义为对象文字语法的一部分,这使您可以编写如

  • 问题内容: 如下面的代码: 输出为: 是否可以将地图的键设置为准确的数据,而不仅仅是对象的地址?怎么样? 问题答案: 使用JSON时,可以在地图中将对象作为键吗? 严格没有。JSON 映射 数据结构是JSON 对象 数据结构,它是名称/值对的集合,其中元素名称必须是字符串。因此,尽管以映射的形式感知并绑定到JSON对象是合理的,但是JSON映射键也必须是字符串- 再次,因为JSON映射是JSON对