如何在 TypeScript 中为对象动态分配属性? [英] How do I dynamically assign properties to an object in TypeScript?

查看:35
本文介绍了如何在 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} 的命名别名,其中 KeysType 是泛型.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 that Record<Keys,Type> is a named alias to {[k: Keys]: Type} where Keys and Type 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆