TypeScript
Template literal types y key remapping
Creación de strings tipados y transformación de nombres de propiedades con template literal types y key remapping dentro de mapped types.
- Última actualización
- Actualizada
- Nivel
- Profundización
TypeScript
Creación de strings tipados y transformación de nombres de propiedades con template literal types y key remapping dentro de mapped types.
Los template literal types construyen unions de strings a partir de literals. El key remapping transforma nombres de propiedades dentro de mapped types.
type EventName = `${"product" | "order"}.${
"created" | "deleted"
}`;type Language = "es" | "en";
type Resource = "title" | "description";
type TranslationKey = `${Language}.${Resource}`;Resultado:
"es.title" |
"es.description" |
"en.title" |
"en.description"Uppercase<"hello">; // "HELLO"
Lowercase<"HELLO">; // "hello"
Capitalize<"product">; // "Product"
Uncapitalize<"Name">; // "name"Estas transformaciones siguen comportamiento interno del compilador y no son locale-aware.
type PropEventSource<T> = {
on<TKey extends string & keyof T>(
event: `${TKey}Changed`,
callback: (value: T[TKey]) => void,
): void;
};source.on("priceChanged", (price) => {
price.toFixed(2);
});El string identifica una propiedad y determina el tipo del callback.
type ExtractEntity<T> =
T extends `${infer TEntity}:${string}`
? TEntity
: never;type Entity = ExtractEntity<"product:123">;
// "product"type RouteParameter<TPath extends string> =
TPath extends `${string}:${infer TParameter}/${infer TRest}`
? TParameter | RouteParameter<TRest>
: TPath extends `${string}:${infer TParameter}`
? TParameter
: never;type Parameters = RouteParameter<
"/products/:productId/reviews/:reviewId"
>;type Getters<T> = {
[K in keyof T as `get${Capitalize<string & K>}`]:
() => T[K];
};type RemoveKind<T> = {
[K in keyof T as K extends "kind" ? never : K]:
T[K];
};Una key transformada a never desaparece.
type FunctionProperties<T> = {
[K in keyof T as T[K] extends (...args: any[]) => any
? K
: never]: T[K];
};type Prefixed<T, TPrefix extends string> = {
[K in keyof T as `${TPrefix}${Capitalize<string & K>}`]:
T[K];
};keyof T puede incluir number o symbol. Para interpolar usa:
string & KEsto conserva solo las claves compatibles con string.
type GetterName = `get${Capitalize<string>}`;No crea funciones ni renombra propiedades reales. La implementación debe construir el objeto correspondiente.
Combinar muchas unions multiplica posibilidades.
type Huge = `${A}${B}${C}${D}`;Para conjuntos grandes o dinámicos, usa string validado o genera tipos durante build en lugar de exigir al checker calcular miles de literals.
Template literal types aportan cuando la API runtime ya utiliza una convención de nombres.
No diseñes un DSL de strings complejo solo para demostrar tipos; un objeto puede ser más fácil de descubrir y refactorizar.
type Resource = "products" | "orders";
type Action = "read" | "create" | "update" | "delete";
type Permission = `${Resource}.${Action}`;as para renombrar o filtrar keys.¿Por qué string & K aparece al construir nombres desde keyof T?
Porque keyof también puede contener number o symbol, y los template literal types necesitan una clave compatible con string.
Utility types reúne transformaciones estándar y explica cuándo no utilizarlas.