La tercera parte de los utility types cubre los que trabajan con funciones y clases en lugar de con objetos. ReturnType, Parameters, ConstructorParameters e InstanceType extraen información de tipos de funciones y clases. Awaited desenvuelve Promises anidadas. Juntos permiten componer tipos sin declararlos a mano, usando el propio código como fuente de verdad.
ReturnType: el tipo que devuelve una función
ReturnType<T> extrae el tipo de retorno de una función. Es útil cuando no controlas la declaración de la función, por ejemplo cuando viene de una librería:
function obtenerUsuario() {
return { id: 1, nombre: "Ana", email: "[email protected]" };
}
type Usuario = ReturnType;
// { id: number; nombre: string; email: string }
// Útil con librerías externas
import { createStore } from "redux";
type TiendaRedux = ReturnType;
Parameters: los tipos de los parámetros
Parameters<T> devuelve una tupla con los tipos de todos los parámetros de la función:
function registrar(nombre: string, edad: number, activo?: boolean): void {}
type ParamsRegistrar = Parameters;
// [nombre: string, edad: number, activo?: boolean]
// Útil para wrappers y decoradores
function logear any>(
fn: F,
...args: Parameters
): ReturnType {
console.log("Llamando con:", args);
return fn(...args);
}
ConstructorParameters: parámetros de un constructor
ConstructorParameters<T> hace lo mismo que Parameters pero para el constructor de una clase. Permite crear instancias de una clase de forma genérica:
class Conexion {
constructor(
private host: string,
private puerto: number,
private ssl: boolean = true
) {}
}
type ArgsConexion = ConstructorParameters;
// [host: string, puerto: number, ssl?: boolean]
function crearConexion(...args: ConstructorParameters): Conexion {
return new Conexion(...args);
}
InstanceType: el tipo de instancia de una clase
InstanceType<T> devuelve el tipo de las instancias de una clase constructora. Es útil cuando trabajas con referencias a clases genéricas o con factories:
class Repositorio {
buscarPorId(id: number): Promise {
return Promise.resolve(null);
}
}
type InstanciaRepo = InstanceType;
// Repositorio (el tipo de instancia, no de la clase)
function crearRepo any>(
Clase: T,
...args: ConstructorParameters
): InstanceType {
return new Clase(...args);
}
Awaited: desenvolver Promises anidadas
Awaited<T> extrae el tipo interior de una Promise, incluidas las Promises anidadas. Es el tipo equivalente a lo que obtienes al hacer await:
type A = Awaited>; // string type B = Awaited >>; // number type C = Awaited >; // string | boolean async function fetchDatos(): Promise<{ id: number; titulo: string }[]> { return fetch("/api/datos").then(r => r.json()); } type Datos = Awaited >; // { id: number; titulo: string }[]
Composición de utility types
Los utility types se pueden combinar. Un patrón habitual es usar Awaited con ReturnType para obtener el tipo resuelto de una función asíncrona:
async function obtenerArticulos() {
const res = await fetch("/api/articulos");
return res.json() as Promise<{ id: number; titulo: string }[]>;
}
type Articulos = Awaited>;
// { id: number; titulo: string }[]
// Ahora puedes usar Articulos en componentes sin redeclarar el tipo
function renderizarLista(articulos: Articulos): string {
return articulos.map(a => a.titulo).join("n");
}
La regla general es: si tienes un valor en el código (una función, una clase, un objeto), usa typeof más uno de estos utility types para extraer el tipo que necesitas. Así el tipo siempre está sincronizado con la implementación real.
Imagen: Pexels / Myburgh Roux
