在Typescript中动态创建对象

时间:2018-07-24 16:49:22

标签: typescript

下面的Javascript代码显示{ x: 1 }

var foo = 'x';
var a = {};
if (foo == 'x')
    a.x = 1;
else
    a.y = 2;
console.log(a);

类似地,我需要在Typescript中动态构建一个对象,换句话说,当我创建该对象时,我不知道它的成员是什么。

我在Typescript中尝试过此操作,但是它不起作用:

let foo = 'x';
let a = {};
if (foo == 'x')
    a.x = 1;    //  <-- transpilation fails here
else
    a.y = 2;    //  <-- transpilation fails here 
console.log(a); 

错误是Property 'x' does not exist on type '{}'.是否可以在Typescript中动态创建对象?

2 个答案:

答案 0 :(得分:4)

TypeScript需要在声明变量时了解对象将具有的字段。默认情况下,根据您分配的内容来推断类型,因为您分配了{},所以a将是没有属性的类型。您可以将a的类型声明为适合您需要的内容:

var foo = 'x';
var a : { x?: number; y?:number} = {}; // Both x and y are optional, hence the ?
if (foo == 'x')
    a.x = 1;
else
    a.y = 2;
console.log(a);

也可以使用a: any,但是您应该避免使用它,因为它会关闭a上的所有检查,这可能不是您想要的,因为打字稿的重点是尽可能多地检查。除非您不知道值的类型和键名,否则我会避免使用any

如果您在编译时不知道键是什么(可能是基于用户输入或服务调用),则还可以使用index signature,该键至少会检查值的类型已验证。例如,仅允许数字值但任何键的类型如下:

var foo = 'x';
var a : { [n: string]: number} = {};
if (foo == 'x')
    a.x = 1;
else
    a.y = 2;
console.log(a);

答案 1 :(得分:3)

如果您确实知道所有可能的字段 ,但您不知道要设置的 ,则可以使用Partial<T>,其中无需创建新接口并将:?放在任何地方,因为您可能希望继承其属性并非都是可选的类型/接口:

interface A {
    x: number;
    y: number;
    z: string;
}

let foo = 'x';
let a: Partial<A> = {};
if (foo == 'x')
    a.x = 1;
else
    a.y = 2; 

如果您不提前知道什么字段可以是 ,因为TypeScript仅提前存在(在编译阶段),因此另一种选择是将其声明为{{ 3}}类型。

let foo = 'x';
let a: any = {};
if (foo == 'x')
    a.x = 1;
else
    a.y = 2; 

然而,这很少是一种理想的方法,因为它完全禁用了类型检查,从而使使用TypeScript进行修饰的目的无法实现。