如果我想在Javascript中以编程方式将一个属性分配给一个对象,我会这样做:
var obj = {};
obj.prop = "value";
但在TypeScript中,这会产生一个错误:
属性“prop”在类型为“{}”的值上不存在
我应该如何在TypeScript中分配任何新属性给对象?
如果我想在Javascript中以编程方式将一个属性分配给一个对象,我会这样做:
var obj = {};
obj.prop = "value";
但在TypeScript中,这会产生一个错误:
属性“prop”在类型为“{}”的值上不存在
我应该如何在TypeScript中分配任何新属性给对象?
当前回答
通过将任何类型的对象类型转换为'any'来存储任何新属性:
var extend = <any>myObject;
extend.NewProperty = anotherObject;
稍后,你可以通过将扩展对象转换回'any'来检索它:
var extendedObject = <any>myObject;
var anotherObject = <AnotherObjectType>extendedObject.NewProperty;
其他回答
尽管编译器抱怨它仍然应该按照你的要求输出它。然而,这是可行的。
const s = {};
s['prop'] = true;
当对象具有特定类型时,此解决方案非常有用。比如从其他源获取对象时。
let user: User = new User();
(user as any).otherProperty = 'hello';
//user did not lose its type here.
索引类型
可以将obj表示为任意值,但这违背了使用typescript的全部目的。obj ={}表示obj是一个对象。把它标记为任何都没有意义。为了实现所需的一致性,可以按照如下方式定义接口。
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;
记录<Keys,Type>实用程序类型
更新(2020年8月):@transang在评论中提到了这一点
Record<Keys,Type>是typescript中的Utility类型。对于属性名未知的键-值对,它是一种更简洁的替代方法。 值得注意的是,Record<Keys,Type>是{[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,
}
虽然这回答了最初的问题,但@GreeneCreations的回答可能会从另一个角度来解决这个问题。
这是Object的一个特殊版本。赋值,它会在每次属性更改时自动调整变量类型。不需要额外的变量、类型断言、显式类型或对象副本:
function assign<T, U>(target: T, source: U): asserts target is T & U {
Object.assign(target, source)
}
const obj = {};
assign(obj, { prop1: "foo" })
// const obj now has type { prop1: string; }
obj.prop1 // string
assign(obj, { prop2: 42 })
// const obj now has type { prop1: string; prop2: number; }
obj.prop2 // number
// const obj: { prop1: "foo", prop2: 42 }
注意:示例使用TS 3.7断言函数。与Object.assign不同,assign的返回类型是void。
只需这样做,您就可以添加或使用任何属性。(我使用的typescript版本为“typescript”:“~4.5.5”)
let contextItem = {} as any;
现在,您可以添加任何属性并在任何地方使用它。就像
contextItem.studentName = "kushal";
之后你可以这样使用它:
console.log(contextItem.studentName);