如果我想在Javascript中以编程方式将一个属性分配给一个对象,我会这样做:
var obj = {};
obj.prop = "value";
但在TypeScript中,这会产生一个错误:
属性“prop”在类型为“{}”的值上不存在
我应该如何在TypeScript中分配任何新属性给对象?
如果我想在Javascript中以编程方式将一个属性分配给一个对象,我会这样做:
var obj = {};
obj.prop = "value";
但在TypeScript中,这会产生一个错误:
属性“prop”在类型为“{}”的值上不存在
我应该如何在TypeScript中分配任何新属性给对象?
当前回答
为Angular扩展@jmvtrinidad解决方案,
当使用已经存在的类型化对象时,这是添加新属性的方法。
let user: User = new User();
(user as any).otherProperty = 'hello';
//user did not lose its type here.
现在如果你想在html端使用otherProperty,这是你需要的:
<div *ngIf="$any(user).otherProperty">
...
...
</div>
Angular编译器将$any()视为转换为any类型,就像TypeScript中使用a <any>或任意类型转换一样。
其他回答
在TypeScript中动态地为对象分配属性。
你只需要像这样使用typescript接口:
interface IValue {
prop1: string;
prop2: string;
}
interface IType {
[code: string]: IValue;
}
你可以这样使用它
var obj: IType = {};
obj['code1'] = {
prop1: 'prop 1 value',
prop2: 'prop 2 value'
};
如果你正在使用Typescript,你可能想要使用类型安全;在这种情况下,naked Object和'any'是相反的。
最好不要使用Object或{},而是使用一些命名类型;或者您可能正在使用具有特定类型的API,您需要使用自己的字段进行扩展。我发现这个方法很有效:
class Given { ... } // API specified fields; or maybe it's just Object {}
interface PropAble extends Given {
props?: string; // you can cast any Given to this and set .props
// '?' indicates that the field is optional
}
let g:Given = getTheGivenObject();
(g as PropAble).props = "value for my new field";
// to avoid constantly casting:
let k = getTheGivenObject() as PropAble;
k.props = "value for props";
索引类型
可以将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的回答可能会从另一个角度来解决这个问题。
你可以用这个:
this.model = Object.assign(this.model, { newProp: 0 });
我写过一篇文章探讨这个话题:
Typescript -在运行时增强对象及其类型
https://tech.xriba.io/2022/03/24/typescript-enhance-an-object-and-its-type-at-runtime/
也许你可以从Typescript概念中获得灵感,比如:
映射类型 通过as键重映射 十字路口类型