如何在typescript接口中迭代可选变量?

时间:2017-01-05 22:50:14

标签: angular typescript

我正在使用一个库,它提供了作为可选的所有成员的typescript接口,没有构造函数,如下所示:

export interface ExampleDto {
    a?: string;
    b?: string;
}

尝试以通常的方式循环成员无处可去(因为对象没有成员,因为它们是可选的):

let ex: ExampleDto = {};
for(let m in ex) {
    console.log(m);
}

如何循环使用ExampleDto并查看“a”和“b”而无需构建所有成员设置的实际ExampleDto?其中一些接口有很多成员。我不在乎价值。我只想迭代可选的成员名称。

基于Meirion Hughes的解释,提出了以下修复方法。 每个接口都是通过Swagger动态生成的,所以我添加了一个empty()函数来创建一个完全填充的对象。我走这条路线是为了避免破坏图书馆的其他用户:

export interface ExampleDto {
  a?: string;
  b?: string;
}
export namespace ExampleDto {
  export function empty(): ExampleDto {
    return {
      a: null,
      b: null,
    }
  }
}

更新2: Typescript 2.1提供了“keyof”,它产生了允许的属性名称的类型。 详细信息: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html

2 个答案:

答案 0 :(得分:3)

接口没有运行时构造。因此,您必须在运行时分配字段以使其存在。如果您希望密钥存在,但值为undefined / null,则必须显式初始化它。您可以通过删除可选项并允许它为undefined类型来强制执行此操作。

interface Foo{
  bar: number | undefined;
}

let bad:Foo = {}; // Error - Property 'bar' is missing in type '{}'.

let good:Foo = {bar:undefined}; // OK

for(let key in good) {
    console.log(key);  // prints bar
}

您可以做的一件事是在有效实例之上应用不完整的可选数据。即,创建实例的基本版本,并将所有字段设置为undefined。然后允许具有一些未设置属性的部分实例。最后,将base和incomplete合并在一起以创建一个包含所有字段的已还原实例:

type Foo = { bar: string | undefined, ray: string | undefined };

let initFoo: Foo = { bar: undefined, ray: undefined };
let incompleteDTO: Partial<Foo> = { ray: "yes" };
let restoredData: Foo = { ...initFoo, ...incompleteDTO };

for (let key in restoredData) {
  console.log(key, restoredData[key]);
}

输出:

bar undefined
ray yes

最后,这种行为更容易通过类使用:

class Foo {
  bar: number | undefined = undefined;
  ray: string | undefined = undefined;

  constructor(init: Partial<Foo>) {
    Object.assign(this, init);
  }
}

let bad: Foo = {}; // Error
let good: Foo = new Foo({ ray: "yes" });

答案 1 :(得分:1)

Typescript接口不是实际的对象或类,它们只是运行时javascript对象结构的定义 在编译时,接口甚至没有被翻译成javascript,也没有构造函数。

在您的代码中,您为ex变量分配了一个空对象,它没有属性 这将打印a

let ex: ExampleDto = {
    a: "A"
};
for(let m in ex) {
    console.log(m);
}