typescript - Typ för konstant strängarray som innehåller en delmängd av strängliteralunionstyp


Jag har en strängliteral unions typ Animal:

type Animal = 'GOAT' | 'GIRAFFE' | 'SALMON' | 'TUNA'

Jag har också en typ Fisk som är en delmängd av Djur:

type Fish = Extract<Animal, 'SALMON' | 'TUNA'> // type Fish = "SALMON" | "TUNA"

Nu vill jag ha en matris av strängar som innehåller fisken, så att jag kan använda den matrisen i logiken (t.ex. för att använda includes()-funktionen). Jag kunde bara definiera matrisen separat:

const FISH: ReadonlyArray<Fish> = ['SALMON', 'TUNA']

men nu måste jag hålla listan över fiskar på två ställen.

Vad jag vill veta är: är det möjligt att använda värdena i arrayen för att definiera vilka strängliteraler som ska extraheras för typen Fish samtidigt som man bara tillåter att arrayen innehåller Animal-strängar?

Något som:

const FISH: ReadonlyArray<SubsetOfStringLiterals<Animal>> = ['SALMON', 'TUNA'] // Would error if it contained a value not in Animal
type Fish = typeof FISH[number] // type Fish = "SALMON" | "TUNA"

där SubsetOfStringLiterals i huvudsak skulle vara ett verktyg som Partial men för föreningstyper av strängliteraler.

Svar #1

Om du vill tillämpa en begränsning på en typ och också dra slutsatsen om något mer specifikt, då måste du antingen använda en generisk funktion eller den nya satisfies-operatorn.


I nästa Typescript-version (4.9, för närvarande i beta) kommer satisfies-operatorn som fungerar bra här.

// fine
const FISH = ['SALMON', 'TUNA'] as const satisfies ReadonlyArray<Animal>

// error
const FISH_BAD = ['COFFEE'] as const satisfies ReadonlyArray<Animal>

Se lekplats


Typescript 4.8 eller lägre, du behöver använda en enkel generisk identitetsfunktion.

function makeSubAnimals<T extends readonly Animal[]>(arr: T) { return arr }

const FISH = makeSubAnimals(['SALMON', 'TUNA'] as const) // fine
const FISH_BAD = makeSubAnimals(['COFFEE'] as const) // error

Se lekplats

Relaterade artiklar