Non esiste un modo semplice per creare un array di chiavi da un'interfaccia. I tipi vengono cancellati in fase di esecuzione e i tipi di oggetto (non ordinati, denominati) non possono essere convertiti in tipi di tupla (ordinati, senza nome) senza una sorta di hack.
Opzione 1: approccio manuale
// 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")[]
(+) semplice (-) tipo restituito da array, nessuna scrittura manuale di tupla (+ -) con completamento automatico
Estensione: potremmo provare a essere fantasiosi e utilizzare tipi ricorsivi per generare una tupla. Questo ha funzionato per me solo per un paio di oggetti di scena (~ 5,6) fino a quando le prestazioni non si sono degradate in modo massiccio. Anche il tipo ricorsivo profondamente annidato non è ufficialmente supportato da TS: elenco questo esempio qui per completezza.
Opzione 2: generatore di codice basato sull'API del compilatore TS ( 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
Dopo aver compilato ed eseguito questo file con tsc && node dist/mybuildstep.js
, ./src/generated/IMyTable-keys.ts
viene generato un file con il seguente contenuto:
// ./src/generated/IMyTable-keys.ts
const keys = ["id","title","createdAt","isDeleted"] as const;
(+) soluzione automatica (+) il tipo esatto di tupla (-) richiede build-step
PS: ho scelto ts-morph
, in quanto è una semplice alternativa all'API del compilatore TS originale.