如何在 TypeScript 中动态分配对象属性?
如果我想以编程方式在 Javascript 中为对象分配属性,我会这样做:
var obj = {};
obj.prop = "value";
但在 TypeScript 中,这会产生错误:
The property 'prop' does not exist on value of type '{}'
如何在 TypeScript 中为对象分配任何新属性?
索引签名
可以将
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 thatRecord<Keys,Type>
is a named alias to{[k: Keys]: Type}
whereKeys
andType
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 在 此处 提供的答案可能会提供关于如何解决问题的另一种观点。
或者一次性全部完成:
var obj:any = {}
obj.prop = 5;
当您的对象具有特定类型时,此解决方案很有用。例如当从其他源获取对象时。
let user: User = new User();
(user as any).otherProperty = 'hello';
//user did not lose its type here.