Es gibt keine einfache Möglichkeit, ein Schlüsselarray über eine Schnittstelle zu erstellen. Typen werden zur Laufzeit gelöscht und Objekttypen (ungeordnet, benannt) können nicht ohne irgendeine Art von Hack in Tupeltypen (geordnet, unbenannt) konvertiert werden.
Option 1: Manueller Ansatz
// 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")[]
(+) einfacher (-) Array-Rückgabetyp, kein Tupel (+ -) manuelles Schreiben mit automatischer Vervollständigung
Erweiterung: Wir könnten versuchen, ausgefallen zu sein und rekursive Typen zu verwenden, um ein Tupel zu generieren. Dies funktionierte nur für ein paar Requisiten (~ 5,6), bis sich die Leistung massiv verschlechterte. Tief verschachtelte rekursive Typen werden von TS auch nicht offiziell unterstützt . Der Vollständigkeit halber liste ich dieses Beispiel hier auf.
Option 2: Codegenerator basierend auf der TS-Compiler-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
Nachdem wir diese Datei kompiliert und ausgeführt haben tsc && node dist/mybuildstep.js, wird eine Datei ./src/generated/IMyTable-keys.tsmit folgendem Inhalt generiert:
// ./src/generated/IMyTable-keys.ts
const keys = ["id","title","createdAt","isDeleted"] as const;
(+) automatische Lösung (+) exakter Tupeltyp (-) erfordert Build-Schritt
PS: Ich habe mich entschieden ts-morph, da es eine einfache Alternative zur ursprünglichen TS-Compiler-API ist.