小编典典

如何在 TypeScript 中为对象动态分配属性?

all

如果我想以编程方式将属性分配给 Javascript 中的对象,我会这样做:

var obj = {};
obj.prop = "value";

但在 TypeScript 中,这会产生错误:

“{}”类型的值上不存在属性“prop”

我应该如何将任何新属性分配给 TypeScript 中的对象?


阅读 156

收藏
2022-03-04

共1个答案

小编典典

索引类型

可以表示objany,但这违背了使用打字稿的全部目的。obj = {}暗示obj是一个Object.
将其标记为any没有意义。为了实现所需的一致性,可以如下定义接口。

interface LooseObject {
    [key: string]: any
}

var obj: LooseObject = {};

或使其紧凑:

var obj: {[k: string]: any} = {};

LooseObject可以接受任何字符串作为键和any类型作为值的字段。

obj.prop = "value";
obj.prop2 = 88;

此解决方案的真正优雅之处在于您可以在界面中包含类型安全字段。

interface MyType {
    typesafeProp1?: number,
    requiredProp1: string,
    [key: string]: any
}

var obj: MyType ;
obj = { requiredProp1: "foo"}; // valid
obj = {} // error. 'requiredProp1' is missing
obj.typesafeProp1 = "bar" // error. typesafeProp1 should be a number

obj.prop = "value";
obj.prop2 = 88;

Record<Keys,Type> 实用类型

更新(2020 年 8 月):@transang 在评论中提出了这一点

Record<Keys,Type>是打字稿中的实用程序类型。对于属性名称未知的键值对,它是一种更简洁的替代方案。值得注意的是where和are
genericsRecord<Keys,Type>的命名别名。IMO,这在这里值得一提{[k: Keys]: Type}``Keys``Type

为了比较,

var obj: {[k: string]: any} = {};

变成

var obj: Record<string,any> = {}

MyType现在可以通过扩展 Record 类型来定义

interface MyType extends Record<string,any> {
    typesafeProp1?: number,
    requiredProp1: string,
}
2022-03-04