如果我想以编程方式将属性分配给 Javascript 中的对象,我会这样做:
var obj = {}; obj.prop = "value";
但在 TypeScript 中,这会产生错误:
“{}”类型的值上不存在属性“prop”
我应该如何将任何新属性分配给 TypeScript 中的对象?
可以表示obj为any,但这违背了使用打字稿的全部目的。obj = {}暗示obj是一个Object. 将其标记为any没有意义。为了实现所需的一致性,可以如下定义接口。
obj
any
obj = {}
Object
interface LooseObject { [key: string]: any } var obj: LooseObject = {};
或使其紧凑:
var obj: {[k: string]: any} = {};
LooseObject可以接受任何字符串作为键和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>是打字稿中的实用程序类型。对于属性名称未知的键值对,它是一种更简洁的替代方案。值得注意的是where和are genericsRecord<Keys,Type>的命名别名。IMO,这在这里值得一提{[k: Keys]: Type}``Keys``Type
更新(2020 年 8 月):@transang 在评论中提出了这一点
Record<Keys,Type>是打字稿中的实用程序类型。对于属性名称未知的键值对,它是一种更简洁的替代方案。值得注意的是where和are genericsRecord<Keys,Type>的命名别名。IMO,这在这里值得一提{[k: Keys]: Type}``Keys``Type
{[k: Keys]: Type}``Keys``Type
为了比较,
变成
var obj: Record<string,any> = {}
MyType现在可以通过扩展 Record 类型来定义
MyType
interface MyType extends Record<string,any> { typesafeProp1?: number, requiredProp1: string, }