インターフェイスからキー配列を作成する簡単な方法はありません。型は実行時に消去され、オブジェクト型(順序なし、名前付き)は、なんらかのハックなしにタプル型(順序付き、名前なし)に変換できません。
オプション1:手動アプローチ
// Record type ensures, we have no double or missing keys, values can be neglected
function createKeys(keyRecord: Record<keyof IMyTable, any>): (keyof IMyTable)[] {
return Object.keys(keyRecord) as any
}
const keys = createKeys({ isDeleted: 1, createdAt: 1, title: 1, id: 1 })
// const keys: ("id" | "title" | "createdAt" | "isDeleted")[]
(+)単純な(-)配列の戻り値型、タプルなし(+-)自動補完による手動書き込み
拡張機能:凝ったデザインにして、再帰型を使用してタプルを生成できます。これは、パフォーマンスが大幅に低下するまで、いくつかの小道具(〜5,6)でしか機能しませんでした。深くネストされた再帰型もTSでは正式にサポートされていません。完全を期すために、ここではこの例を挙げます。
オプション2:TSコンパイラAPIに基づくコードジェネレーター(ts-morph)
// ./src/mybuildstep.ts
import {Project, VariableDeclarationKind, InterfaceDeclaration } from "ts-morph";
const project = new Project();
// source file with IMyTable interface
const sourceFile = project.addSourceFileAtPath("./src/IMyTable.ts");
// target file to write the keys string array to
const destFile = project.createSourceFile("./src/generated/IMyTable-keys.ts", "", {
overwrite: true // overwrite if exists
});
function createKeys(node: InterfaceDeclaration) {
const allKeys = node.getProperties().map(p => p.getName());
destFile.addVariableStatement({
declarationKind: VariableDeclarationKind.Const,
declarations: [{
name: "keys",
initializer: writer =>
writer.write(`${JSON.stringify(allKeys)} as const`)
}]
});
}
createKeys(sourceFile.getInterface("IMyTable")!);
destFile.saveSync(); // flush all changes and write to disk
このファイルをでコンパイルして実行すると、次の内容のtsc && node dist/mybuildstep.jsファイル./src/generated/IMyTable-keys.tsが生成されます。
// ./src/generated/IMyTable-keys.ts
const keys = ["id","title","createdAt","isDeleted"] as const;
(+)自動ソリューション(+)正確なタプルタイプ(-)にはビルドステップが必要
PS:を選択ts-morphしました。これは、元のTSコンパイラAPIの単純な代替手段であるためです。