TypeScript-Version: 3.0.3
Suchbegriffe: Geben Sie basierend auf den Werten im Array ein
Gibt es eine aktuelle oder geplante Funktion zum Erstellen eines Typs aus Zeichenfolgen in einem Array?
Code
const values = ['A', 'B']
type Foo = OneOf<values> // Is there a way of doing this?
const v1: Foo = 'A' // This should work
const v2: Foo = 'D' // This should give me an error since 'D' doesn't exist in values
Ähnlich wie keyof
funktioniert:
const values = {
A: 'A',
B: 'B'
}
type Foo = keyof typeof values
const v1: Foo = 'A'
const v2: Foo = 'D' // Type '"D"' is not assignable to type '"A" | "B"'
Verwandte Themen:https://github.com/Microsoft/TypeScript/issues/20965
Link zum Spielplatz http://www.typescriptlang.org/play/#src = let% 20vals1% 20% 3D% 20% 5B'A '% 2C% 20'B'% 5D% 0D% 0Atype% 20Foo1% 20% 3D% 20OneOf% 3Cvals1% 3E% 20% 2F% 2F% 20Is% 20there% 20a% 20way% 20of% 20doing% 20this% 3F% 0D% 0A% 0D% 0Alet% 20v1% 3A% 20Foo1% 20% 3D% 20 ' A '% 20% 2F% 2F% 20This% 20should% 20work% 0D% 0Alet% 20v2% 3A% 20Foo1% 20% 3D% 20'D'% 20% 2F% 2F% 20This% 20should% 20give% 20me% 20an% 20error% 20since% 20'D '% 20doses% 20exist% 20in% 20values% 0D% 0A% 0D% 0Alet% 20vals2% 20% 3D% 20% 7B% 0D% 0A% 20% 20A% 3A% 20'A '% 2C% 0D% 0A% 20% 20B% 3A% 20'B'% 0D% 0A% 7D% 0D% 0Atype% 20Foo2% 20% 3D% 20keyof% 20typeof% 20vals2% 0D% 0Alet% 20v3% 3A% 20Foo2 % 20% 3D% 20'A '% 0D% 0Alet% 20v4% 3A% 20Foo2% 20% 3D% 20'D'% 20% 2F% 2F% 20Type% 20 '% 22D% 22'% 20ist% 20not% 20zuweisbar % 20 bis% 20 Typ% 20 '% 22A% 22% 20% 7C% 20% 22B% 22'
keyof
funktioniert nur, weil Informationen verwendet werden, die zur Kompilierungszeit statisch bekannt sind. Typen in TS sind vollständig löschbar und im transpilierten Code nicht vorhanden. Daher ist es einfach nicht möglich, einen Typ basierend auf dem Laufzeitinhalt eines Arrays zu erstellen.
Das ist möglich:
function stringLiterals<T extends string>(...args: T[]): T[] { return args; }
type ElementType<T extends ReadonlyArray<unknown>> = T extends ReadonlyArray<infer ElementType> ? ElementType : never;
const values = stringLiterals('A', 'B');
type Foo = ElementType<typeof values>;
const v1: Foo = 'A' // This should work
const v2: Foo = 'D' // This should give me an error since 'D' doesn't exist in values
Auf jeden Fall nicht klar, wie das geht. # 27179 ist verwandt.
Dabei werden immer noch Informationen verwendet, die dem Compiler statisch bekannt sind. An diesem Punkt verstehe ich nicht, was der Vorteil ist, wenn man nur ”A” | “B”
sagt.
@fatcerberus Es ist nützlich, das Wiederholen von Informationen zu vermeiden. Wenn Sie nur const values = ["A", "B"]; type Foo = "A" | "B";
schreiben, kann jemand leicht einen von ihnen ändern, während er vergisst, den anderen zu ändern. Sie könnten const values: Foo[] =["A", "B"];
schreiben, aber das ist immer noch anfällig dafür, Foo
einen zusätzlichen Eintrag hinzuzufügen und zu vergessen, ihn in values
.
Wo sind wir jetzt dabei?
Wie @ andy-ms sagte, wäre es wirklich nützlich, Informationen nicht manuell zu wiederholen.
Und wie @fatcerberus sagte, sind Typen vollständig löschbar. Manchmal müssen wir Daten zur Laufzeit überprüfen, die wir beispielsweise von einem nicht reinen Teil der Anwendung (wie dem Webservice oder vom Benutzer) erhalten.
Aufbauend auf der Antwort von @ andy-ms und unter Verwendung der in Typoskript 3.4 eingeführten const-Zusicherungen ist es jetzt möglich, so etwas zu tun
const values = ['A', 'B'] as const
type ElementType < T extends ReadonlyArray < unknown > > = T extends ReadonlyArray<
infer ElementType
>
? ElementType
: never
type Foo = ElementType<typeof values> // this is correctly inferred as literal "A" | "B"
Dieses Problem wurde als "Frage" markiert und hat in letzter Zeit keine Aktivitäten erfahren. Es wurde automatisch für Haushaltszwecke geschlossen. Wenn Sie immer noch auf eine Antwort warten, sind Fragen normalerweise besser für den Stapelüberlauf geeignet.
in [email protected] und höher. Löse es so
export const type = <const>[
'room',
'room_with_gifter',
'user_send'
];
export interface Activity {
id?: string;
type: typeof type[number];
}
An Stelle von:
export const items = <const>[
'room',
'room_with_gifter',
'user_send'
];
export interface Activity {
id?: string;
type: typeof items[number];
}
Du kannst das:
export const items = [
'room',
'room_with_gifter',
'user_send'
] as const;
export type Item = typeof items;
export interface Activity {
id?: string;
type: Item;
}
Ich mag es wirklich nicht, type
als Variablennamen zu verwenden.
@ 7 km
in [email protected] und höher. Löse es so
export const type = <const>[ 'room', 'room_with_gifter', 'user_send' ]; export interface Activity { id?: string; type: typeof type[number]; }
Was ist, wenn ich das in einer Klasse habe?
class Class {
const list = <const>[
'room',
'room_with_gifter',
'user_send'
];
const withType: typeof list[number];
}
Funktioniert nicht. Ich kann auch nicht this.list[number]
. Auch für meine besondere
In diesem Fall kann ich list
nicht auf static
@ 7 km
in [email protected] und höher. Löse es so
export const type = <const>[ 'room', 'room_with_gifter', 'user_send' ]; export interface Activity { id?: string; type: typeof type[number]; }
Was ist, wenn ich das in einer Klasse habe?
class Class { const list = <const>[ 'room', 'room_with_gifter', 'user_send' ]; const withType: typeof list[number]; }
Funktioniert nicht. Ich kann auch nicht
this.list[number]
. Auch für meine besondere
In diesem Fall kann ichlist
nicht aufstatic
@vegerot Sie können const
direkt im Bereich von class
, daher ist die Syntax falsch.
@ 7 km
in [email protected] und höher. Löse es so
export const type = <const>[ 'room', 'room_with_gifter', 'user_send' ]; export interface Activity { id?: string; type: typeof type[number]; }
Was ist, wenn ich das in einer Klasse habe?
class Class { const list = <const>[ 'room', 'room_with_gifter', 'user_send' ]; const withType: typeof list[number]; }
Funktioniert nicht. Ich kann auch nicht
this.list[number]
. Auch für meine besondere
In diesem Fall kann ichlist
nicht aufstatic
@vegerot Sie können
const
direkt im Bereich vonclass
, daher ist die Syntax falsch.
@ 7kms Mein schlechtes. Ich habe zu viel kopiert und eingefügt. Was ich sagen wollte ist
class Class {
private list = <const>[
'room',
'room_with_gifter',
'user_send'
];
private withType: typeof list[number];
// OR
private withType2: typeof this.list[number];
}
usw. alle funktionieren nicht.
Außerdem kann ich für meinen speziellen Anwendungsfall die Liste nicht statisch festlegen
@ 7 km
in [email protected] und höher. Löse es so
export const type = <const>[ 'room', 'room_with_gifter', 'user_send' ]; export interface Activity { id?: string; type: typeof type[number]; }
Was ist, wenn ich das in einer Klasse habe?
class Class { const list = <const>[ 'room', 'room_with_gifter', 'user_send' ]; const withType: typeof list[number]; }
Funktioniert nicht. Ich kann auch nicht
this.list[number]
. Auch für meine besondere
In diesem Fall kann ichlist
nicht aufstatic
@vegerot Sie können
const
direkt im Bereich vonclass
, daher ist die Syntax falsch.@ 7kms Mein schlechtes. Ich habe zu viel kopiert und eingefügt. Was ich sagen wollte ist
class Class { private list = <const>[ 'room', 'room_with_gifter', 'user_send' ]; private withType: typeof list[number]; // OR private withType2: typeof this.list[number]; }
usw. alle funktionieren nicht.
Außerdem kann ich für meinen speziellen Anwendungsfall die Liste nicht statisch festlegen
class Class {
private list = [
"room",
"room_with_gifter",
"user_send"
] as const
private withType: Class["list"][number]
}
@vegerot Wie wäre es damit?
@eyalch das ist typeof
oder so beinhalten. Würden Sie kurz erklären, wie das funktioniert, oder mich mit dem Handbuch verknüpfen, in dem dies besprochen wird?
@eyalch das ist
typeof
oder so beinhalten. Würden Sie kurz erklären, wie das funktioniert, oder mich mit dem Handbuch verknüpfen, in dem dies besprochen wird?
@vegerot Klar, ich glaube es ist ein " https://www.typescriptlang.org/docs/handbook/advanced-types.html#index -types
Froh, dass ich helfen konnte!
Hey% username%, wenn die Lösung ElementType
auch bei Ihnen nicht funktioniert,
Achten Sie auf as const
nach dem Array . Es ist entscheidend
Hilfreichster Kommentar
in [email protected] und höher. Löse es so