如何在 TypeScript 中为对象动态分配属性? [英] How do I dynamically assign properties to an object in TypeScript?
问题描述
如果我想以编程方式为 Javascript 中的对象分配一个属性,我会这样做:
var obj = {};obj.prop = "值";
但是在 TypeScript 中,这会产生一个错误:
<块引用>属性prop"不存在于类型{}"的值
我应该如何为 TypeScript 中的对象分配任何新属性?
索引类型
可以将 obj
表示为 any
,但这违背了使用 typescript 的全部目的.obj = {}
暗示 obj
是一个 Object
.将其标记为 any
没有任何意义.为了实现所需的一致性,可以如下定义接口.
interface LooseObject {[键:字符串]:任何}var obj:LooseObject = {};
或使其紧凑:
var obj: {[k: string]: any} = {};
LooseObject
可以接受任何字符串作为键和 any
类型作为值的字段.
obj.prop = 值";obj.prop2 = 88;
此解决方案的真正优雅之处在于您可以在界面中包含类型安全字段.
interface MyType {typesafeProp1?: 数字,requiredProp1:字符串,[键:字符串]:任何}无功对象:我的类型;obj = { requiredProp1: foo"};//有效的obj = {}//错误.缺少requiredProp1"obj.typesafeProp1 = "bar";//错误.typesafeProp1 应该是一个数字obj.prop =值";obj.prop2 = 88;
记录<键,类型>
实用程序类型
<块引用>更新(2020 年 8 月):@transang 在评论中提出了这一点
<块引用>
Record
是 typescript 中的 Utility 类型.对于属性名称未知的键值对,它是一种更简洁的替代方法.值得注意的是,Record
是 {[k: Keys]: Type}
的命名别名,其中 Keys
和 Type
是泛型.IMO,这使得这里值得一提
为了比较,
var obj: {[k: string]: any} = {};
变成
var obj: Record= {}
MyType
现在可以通过扩展 Record 类型来定义
interface MyType extends Record{typesafeProp1?: 数字,requiredProp1:字符串,}
<块引用>
虽然这回答了原始问题,但@GreeneCreations 此处的答案可能会提供有关如何解决问题的另一种视角.
If I wanted to programatically assign a property to an object in Javascript, I would do it like this:
var obj = {};
obj.prop = "value";
But in TypeScript, this generates an error:
The property 'prop' does not exist on value of type '{}'
How am I supposed to assign any new property to an object in TypeScript?
Index types
It is possible to denote obj
as any
, but that defeats the whole purpose of using typescript. obj = {}
implies obj
is an Object
. Marking it as any
makes no sense. To accomplish the desired consistency an interface could be defined as follows.
interface LooseObject {
[key: string]: any
}
var obj: LooseObject = {};
OR to make it compact:
var obj: {[k: string]: any} = {};
LooseObject
can accept fields with any string as key and any
type as value.
obj.prop = "value";
obj.prop2 = 88;
The real elegance of this solution is that you can include typesafe fields in the interface.
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>
utility type
Update (August 2020): @transang brought this up in comments
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
For comparison,
var obj: {[k: string]: any} = {};
becomes
var obj: Record<string,any> = {}
MyType
can now be defined by extending Record type
interface MyType extends Record<string,any> {
typesafeProp1?: number,
requiredProp1: string,
}
While this answers the Original question, the answer here by @GreeneCreations might give another perspective on how to approach the problem.
这篇关于如何在 TypeScript 中为对象动态分配属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!