Ich habe viele Tabellen in Lovefield und ihre jeweiligen Schnittstellen für die Spalten, die sie haben.
Beispiel:
export interface IMyTable {
id: number;
title: string;
createdAt: Date;
isDeleted: boolean;
}
Ich möchte die Eigenschaftsnamen dieser Schnittstelle in einem Array wie diesem haben:
const IMyTable = ["id", "title", "createdAt", "isDeleted"];
Ich kann kein Objekt / Array basierend auf der Schnittstelle IMyTable
direkt erstellen, was den Trick tun sollte, da ich die Schnittstellennamen der Tabellen dynamisch erhalten würde. Daher muss ich diese Eigenschaften in der Schnittstelle durchlaufen und ein Array daraus erstellen.
Wie erreiche ich dieses Ergebnis?
quelle
ts_transformer_keys_1.keys is not a function
wenn ich die genauen Schritte in der Dokumentation befolge. Gibt es eine Problemumgehung?ts_transformer_keys_1.keys is not a function
Im Folgenden müssen Sie die Schlüssel selbst auflisten, aber mindestens TypeScript erzwingt
IUserProfile
und verfügtIUserProfileKeys
über genau dieselben Schlüssel (Required<T>
wurde in TypeScript 2.8 hinzugefügt ):quelle
IUserProfile
und es wäre einfach, sie aus der Konstante zu extrahierenIUserProfileKeys
. Genau das habe ich gesucht. Sie müssen jetzt nicht alle meine Schnittstellen in Klassen konvertieren.Ich hatte ein ähnliches Problem, dass ich eine riesige Liste von Eigenschaften hatte, für die ich sowohl eine Schnittstelle als auch ein Objekt haben wollte.
HINWEIS: Ich wollte die Eigenschaften nicht zweimal schreiben (mit Tastatur eingeben)! Einfach trocken.
Hierbei ist zu beachten, dass Schnittstellen zur Kompilierungszeit erzwungene Typen sind, während Objekte meistens zur Laufzeit ausgeführt werden. ( Quelle )
Wie @derek in einer anderen Antwort erwähnt hat , kann der gemeinsame Nenner von Schnittstelle und Objekt eine Klasse sein, die sowohl einem Typ als auch einem Wert dient .
Also, TL; DR, der folgende Code sollte die Anforderungen erfüllen:
( Hier ist der obige Code in Typescript Playground, um mehr zu spielen)
PS. Wenn Sie den Eigenschaften in der Klasse keine Anfangswerte zuweisen und beim Typ bleiben möchten, können Sie den Konstruktortrick ausführen:
Konstruktor-Trick auf dem TypeScript-Spielplatz .
quelle
propsArray
Zugriff ist jedoch nur möglich, wenn Sie die Schlüssel initialisiert haben.propsArray
steht es vor demtableInstance
Wenn Sie das meinen, also deutlich vor der Initialisierung der Instanz. Wenn Sie sich jedoch auf die in zugewiesenen gefälschten Werte beziehenMyTableClass
, sind diese nur dazu da, kurz den "Typ" der Eigenschaften zu implizieren. Wenn Sie sie nicht möchten, können Sie den Konstruktortrick im PS-Beispiel verwenden.MyTableClass
letzteren ersetzen können und erwarten, dass Sie Schlüssel erhalten,propsArray
wenn nicht initialisierte Variablen und Typen zur Laufzeit entfernt werden. Sie müssen ihnen immer einen Standardwert geben. Ich habe festgestellt, dass das Initialisieren mitundefined
dem besten Ansatz ist.readonly
und?
auf den Parametern. Ich habe das gerade aktualisiert. Vielen Dank für den Hinweis. Jetzt denke ich, dass es so funktioniert, wie Sie es gesagt haben, irreführend ist und nicht funktionieren kann. :)Das sollte funktionieren
oder
quelle
var IMyTable: Array<keyof IMyTable> = ["id", "createdAt", "id"];
IMyTable
Versuchen Sie, es als Klasse zu definieren, anstatt es wie in der Schnittstelle zu definieren. In Typoskript können Sie eine Klasse wie eine Schnittstelle verwenden.Definieren / generieren Sie Ihre Klasse für Ihr Beispiel folgendermaßen:
Verwenden Sie es als Schnittstelle:
Schlüssel erhalten:
quelle
Sie müssen eine Klasse erstellen, die Ihre Schnittstelle implementiert, instanziieren und dann verwenden
Object.keys(yourObject)
, um die Eigenschaften abzurufen.dann
quelle
Cannot extend an interface […]. Did you mean 'implements'?
Verwendungimplements
muss jedoch die Schnittstelle manuell kopiert werden, was genau das ist, was ich nicht möchte.implements
und ich habe meine Antwort aktualisiert. Wie @basarat angegeben hat, existieren Schnittstellen zur Laufzeit nicht. Die einzige Möglichkeit besteht darin, sie als Klasse zu implementieren.@types/react
). Ich habe sie manuell kopiert, aber das ist kaum zukunftssicher. Trying Ich versuche, Nicht-Lebenszyklus-Methoden (die bereits gebunden sind) dynamisch zu binden, aber sie sind nicht in React.Component (der Klasse) deklariert.Kippen. Schnittstellen existieren zur Laufzeit nicht.
Problemumgehung
Erstellen Sie eine Variable des Typs und verwenden Sie
Object.keys
sie 🌹quelle
var abc: IMyTable = {}; Object.keys(abc).forEach((key) => {console.log(key)});
var abc: IMyTable = {}
Da das leere Objektliteral nicht der Form dieser Schnittstelle entspricht.Vielleicht ist es zu spät, aber in Version 2.1 des Typoskripts können Sie Folgendes verwenden
key of
:Doc: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html#keyof-and-lookup-types
quelle
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
(+) 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 )
Nachdem wir diese Datei kompiliert und ausgeführt haben
tsc && node dist/mybuildstep.js
, wird eine Datei./src/generated/IMyTable-keys.ts
mit folgendem Inhalt generiert:(+) 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.quelle
Du kannst es nicht tun. Zur Laufzeit gibt es keine Schnittstellen (wie @basarat sagte).
Jetzt arbeite ich mit Folgendem:
quelle
quelle
console.log(Tes.id)
, natürlich der Fehler "Nicht erfasster Referenzfehler: Tes ist nicht definiert" ist