开发者问题收集

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

2012-10-03
1005227

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

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

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

The property 'prop' does not exist on value of type '{}'

如何在 TypeScript 中为对象分配任何新属性?

3个回答

索引签名

可以将 obj 表示为 any ,但这违背了使用 typescript 的整个目的。 obj = { 意味着 obj 是一个 Object 。将其标记为 any 毫无意义。为了实现所需的一致性,可以按如下方式定义接口,使用 索引签名

interface LooseObject {
    [key: string]: any
}

var obj: LooseObject = {};

或使其紧凑:

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

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

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> 实用程序类型 在注释中

Record<Keys,Type> is a Utility type in typescript. It is a much cleaner alternative for key-value pairs where property-names are not known. It's worth noting that Record<Keys,Type> is a named alias to {[k: Keys]: Type} where Keys and Type are generics. IMO, this makes it worth mentioning here

为了进行比较,

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

变为

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

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

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

虽然这回答了原始问题,但@GreeneCreations 在 此处 提供的答案可能会提供关于如何解决问题的另一种观点。

Akash
2017-06-08

或者一次性全部完成:

  var obj:any = {}
  obj.prop = 5;
Crwth
2012-10-03

当您的对象具有特定类型时,此解决方案很有用。例如当从其他源获取对象时。

let user: User = new User();
(user as any).otherProperty = 'hello';
//user did not lose its type here.
jmvtrinidad
2016-08-25