【问题标题】:How to iterate over optional variables in a typescript interface?如何在打字稿界面中迭代可选变量?
【发布时间】:2017-01-13 02:12:35
【问题描述】:

我正在使用一个库,该库提供 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

【问题讨论】:

    标签: angular typescript


    【解决方案1】:

    接口没有运行时构造。因此,您必须分配该字段以使其在运行时存在。如果您希望密钥存在,但具有 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
    }
    

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

    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" });
    

    【讨论】:

    • 您应该明确指出,这仅适用于 Typescript 2.1 及以后的版本。许多人仍然没有那种奢侈,而这种技术虽然很酷,但对他们不起作用。
    • 感谢您的详尽解释。这真的帮助我找到了前进的方向。
    【解决方案2】:

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

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

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

    【讨论】:

      猜你喜欢
      • 2018-02-04
      • 2017-04-24
      • 2018-10-03
      • 2018-12-04
      • 2018-08-05
      • 2019-02-07
      • 2015-09-06
      • 2016-09-22
      • 2016-06-21
      相关资源
      最近更新 更多