Estoy tratando de obtener una unión literal de cadena basada en valores pasados a una matriz de clases a través del constructor.
Por ejemplo, la matriz se ve así:
const myArray = [ new MyClass({ key: "key1", }), new MyClass({ key: "key2", }), ]Y estoy tratando de construir una versión asignada (para búsqueda) o una unión literal de cadena:
type MyUnionType = "key1" | "key2"La razón principal de esto es garantizar que cualquier búsqueda use las claves disponibles asignadas a la clase.
getClass('key1') // all good getClass('notAKey') // errorSin embargo, todas las soluciones que he visto hasta ahora incluyen alguna forma de redundancia al pasar la clave como genérica o al crear un objeto con las mismas claves.
Puedes hacer algo como esto:
type MyUnionType = { [K in keyof typeof myArray]: (typeof myArray)[K] extends MyClass<infer T> ? T : never }[number] Este es un tipo asignado que revisa cada clave en la matriz y luego infiere el parámetro genérico de cada miembro de myArray .
Esto supone una clase como:
class MyClass<T extends string> { constructor(options: { key: T }) {} }Que usarías como:
const myArray = [ new MyClass({ key: "key1", }), new MyClass({ key: "key2", }), ] as const function getClass(input: MyUnionType) {} getClass('key1') // works getClass('notAKey') // errorO, parametrizado para mayor flexibilidad:
type MyUnionType<T extends readonly MyClass<string>[]> = { [K in keyof T]: T[K] extends MyClass<infer U> ? U : never }[number] function getClass(input: MyUnionType<typeof myArray>) {} getClass('key1') // works getClass('notAKey') // error