Typescript: Erstellen von Typen aus Werten im Array

Erstellt am 22. Okt. 2018  ·  16Kommentare  ·  Quelle: microsoft/TypeScript


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'

Question

Hilfreichster Kommentar

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];
}

Alle 16 Kommentare

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;
}

image

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 ich list nicht auf static

@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 ich list nicht auf static

@vegerot Sie können const direkt im Bereich von class , 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 ich list nicht auf static

@vegerot Sie können const direkt im Bereich von class , 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

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen

Verwandte Themen

manekinekko picture manekinekko  ·  3Kommentare

MartynasZilinskas picture MartynasZilinskas  ·  3Kommentare

weswigham picture weswigham  ·  3Kommentare

blendsdk picture blendsdk  ·  3Kommentare

fwanicka picture fwanicka  ·  3Kommentare