Quiero crear un tipo en TypeScript y usar valores de otro objeto para sus claves.
const routes = { home: "HOME", profile: "PROFILE" } export type NavigatorParamList = { [routes.home]: undefined; [routes.profile]: undefined; };¡Sé que este código no funciona! ¿Alguna idea de cómo hacerlo?
Las propiedades de su objeto son cadenas variables y TypeScript no le permitirá usarlas como propiedades calculadas para un tipo a menos que las convierta en literales de solo lectura con as const .
const routes = { home: "HOME", profile: "PROFILE" } as const;Esto es para lo que son las enumeraciones de cadenas :
enum Route { Home = "HOME", Profile = "PROFILE" } // using a union of individual enum members: type NavigatorParamList1 = Record<Route.Home | Route.Profile, undefined>; // { HOME: undefined; PROFILE: undefined; } // or if you want to use all enum members: type NavigatorParamList2 = Record<Route, undefined>; // { HOME: undefined; PROFILE: undefined; } // or independently-defined members type NavigatorParamList3 = { [Route.Home]: undefined; [Route.Profile]: undefined; }Es factible con tipos mapeados y la nueva cláusula as :
const routes = { home: "HOME", profile: "PROFILE" } as const; type AcceptableKeyTypes = string | number | symbol; type ObjectWithValuesWhichCanBeKeys = {[key: AcceptableKeyTypes]: AcceptableKeyTypes}; type ValuesAsKeys<T extends ObjectWithValuesWhichCanBeKeys> = {[P in keyof T as T[P]]: unknown}; let test: ValuesAsKeys<typeof routes> = {HOME: 7, PROFILE: 4};patio de recreo mecanografiado
Estoy usando aquí un tipo genérico: ValuesAsKeys<T> .
Los valores de T deben restringirse a tipos que sean aceptables como claves: cadena | número | símbolo.
la parte [P in keyof T] es un tipo asignado, que itera sobre todas las claves de T. Luego, la cláusula as asigna la clave a un nuevo valor, en este caso a T[P] , que es el valor de la clave actual clave iterada.
Por último, el valor es desconocido, por lo que puede usar cualquier valor nuevo que desee. en el ejemplo que doy, estoy usando números como los nuevos valores, pero puede ser cualquier cosa.
Tenga en cuenta que, como se dijo en otras respuestas, las routes deben tener la aserción as const , de modo que los valores de cadena se consideren tipos literales y luego se puedan usar como claves escritas.