我正在使用一个库,它提供了作为可选的所有成员的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
答案 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);
}