我在Lovefield中有很多表,以及它们各自的接口,说明它们有哪些列。
例子:
export interface IMyTable {
id: number;
title: string;
createdAt: Date;
isDeleted: boolean;
}
我想有这个接口的属性名在这样的数组中:
const IMyTable = ["id", "title", "createdAt", "isDeleted"];
我不能直接基于接口IMyTable创建一个对象/数组,因为我将动态地获得表的接口名称。因此,我需要在接口中迭代这些属性,并从中获得一个数组。
我如何实现这个结果?
如果您不能使用自定义转换器(或不愿意使用),我认为最好的方法就是我将要展示的方法,它具有以下优点:
它允许“半自动”填充数组(至少在VS Code中);
它会生成一个数组,TypeScript会将其识别为包含接口键的并集元素;
它不涉及降低性能的递归技巧。
方法如下:
interface Foo {
fizz?: string;
buzz: number;
}
const FooKeysEnum: { [K in keyof Required<Foo>]: K } = {
fizz: 'fizz',
buzz: 'buzz',
};
const FooKeys = Object.values(FooKeysEnum);
VS Code中“半自动”填充数组的原因是,当FooKeysEnum因为缺少属性而出现红色下划线时,你可以将鼠标悬停在它上面,从“快速修复”菜单中选择“添加缺少属性”。(这个好处已经在这篇文章中展示过了,但我认为还没有人提到过。埃塔:我弄错了;自动补全已经在线程的其他地方提到了。)
最后,通过使用Object.values()而不是Object.keys()来创建数组,你可以让TypeScript识别出FooKeys的类型是("fizz" | "buzz")[]。它不知道FooKeys[0]是“fizz”,FooKeys[1]是“buzz”,但仍然比你用Object.keys()得到的字符串[]要好。
编辑:
在VS Code中,你也可以在键盘绑定中设置快捷键。json用于执行“Quick Fix”,这使得它可以更快地触发添加缺失的属性。看起来是这样的:
{
"key": "shift+cmd+a",
"command": "editor.action.codeAction",
"args": {
"kind": "quickfix",
"apply": "ifSingle"
}
}
然后,如果某个东西有红色下划线,你可以单击它并使用键盘快捷键,如果只有一个可用的快速修复选项,那么它将运行。如果有一种方法可以针对特定的快速修复,那就太好了,如果它可以在文件保存时自动完成,那就更好了,但我认为在撰写本文时这是不可能的。
不要将IMyTable定义为在接口中,而是尝试将它定义为一个类。在typescript中,你可以像接口一样使用类。
对于你的例子,像这样定义/生成你的类:
export class IMyTable {
constructor(
public id = '',
public title = '',
public createdAt: Date = null,
public isDeleted = false
)
}
使用它作为接口:
export class SomeTable implements IMyTable {
...
}
得到键:
const keys = Object.keys(new IMyTable());
我也遇到过类似的问题:我有一个巨大的属性列表,我既想将其作为接口(编译时),也想将其作为对象(运行时)。
注意:我不想写(用键盘输入)两次属性!干了。
这里需要注意的一点是,接口是在编译时强制执行的类型,而对象主要是在运行时强制执行的类型。(源)
正如@derek在另一个回答中提到的,接口和对象的共同点可以是同时服务于类型和值的类。
因此,TL;DR,下面的一段代码应该可以满足需求:
class MyTableClass {
// list the propeties here, ONLY WRITTEN ONCE
id = "";
title = "";
isDeleted = false;
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// This is the pure interface version, to be used/exported
interface IMyTable extends MyTableClass { };
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Props type as an array, to be exported
type MyTablePropsArray = Array<keyof IMyTable>;
// Props array itself!
const propsArray: MyTablePropsArray =
Object.keys(new MyTableClass()) as MyTablePropsArray;
console.log(propsArray); // prints out ["id", "title", "isDeleted"]
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Example of creating a pure instance as an object
const tableInstance: MyTableClass = { // works properly!
id: "3",
title: "hi",
isDeleted: false,
};
(这里是上面的Typescript Playground代码,可以玩更多)
PS.如果你不想给类中的属性赋初始值,而保持类型,你可以使用构造函数技巧:
class MyTableClass {
// list the propeties here, ONLY WRITTEN ONCE
constructor(
readonly id?: string,
readonly title?: string,
readonly isDeleted?: boolean,
) {}
}
console.log(Object.keys(new MyTableClass())); // prints out ["id", "title", "isDeleted"]
TypeScript游乐场中的构造函数技巧。