Website-Suche

typescript - Argument des Typs 'string' kann dem Parameter vom Typ Vereinigung von string-Konstanten nicht zugewiesen werden


Einmal mehr bin ich hier und suche nach ein wenig Anleitung zu TypeScript-Heuristiken. Ich habe Schwierigkeiten, einen Typ-Guard zu schreiben, weil TypeScript beim Vergleichen zu engstirnig sein will.

Betrachten Sie das folgende Szenario (oder den Typescript Playground):

const FOO = 'foo' as const;
const BAR = 'bar' as const;

const ALL_THINGS = [FOO, BAR];
type AllThingsType = typeof ALL_THINGS[number];

function isAllThings(value: unknown): value is AllThingsType {
  return typeof value === 'string' && ALL_THINGS.includes(value);
}

Der Fehler wird der folgende sein:

Argument of type 'string' is not assignable to parameter of type '"foo" | "bar"'.ts(2345)

Es gibt technisch gesehen eine Möglichkeit, dies zu umgehen:

function isAllThingsWorkaround(value: unknown): value is AllThingsType {
  return typeof value === 'string' && (ALL_THINGS as string[]).includes(value);
}

Fehlt mir etwas in Bezug darauf, wie ich das machen sollte? Der von mir geteilte Ausschnitt ist eine vereinfachte Version, du kannst davon ausgehen, dass ALL_THINGS tatsächlich eine Sammlung von fast 25 Konstanten ist. Wie könnte ich das verbessern, um den Workaround zu vermeiden?

Danke für die Hilfe!

Antwort #1

Eine Möglichkeit, dies zu tun, besteht darin, .includes nicht zu verwenden.

const FOO = 'foo' as const;
const BAR = 'bar' as const;

const ALL_THINGS = [FOO, BAR];
type AllThingsType = typeof ALL_THINGS[number];

function isAllThings(value: unknown): value is AllThingsType {
  return typeof value === 'string' && ALL_THINGS.some(a => a === value);
}

console.log(isAllThings("cat")); // false
console.log(isAllThings("foo")); // true

Dieser Weg erfordert keinen Typumwandlung, und Sie können selbst entscheiden, was „includes“ tatsächlich bedeutet, anstatt JavaScript entscheiden zu lassen.

Verwandte Artikel