Historia de la pregunta
Con el desarrollo de TypeScript, surgió la necesidad de extraer automáticamente el tipo de valor de retorno de una función, especialmente para proyectos grandes con muchas funciones interconectadas. Para esto se introdujo el tipo utilitario ReturnType<T>, que apareció en la biblioteca estándar a partir de la versión 2.8 de TypeScript.
Problema
En proyectos grandes y complejos, a veces es difícil mantener la actualización de los tipos; si se indica manualmente el tipo de retorno de cada función y se produce un cambio en las firmas, es fácil obtener inconsistencias cuando las firmas y las implementaciones no coinciden. Además, si una función devuelve una estructura compleja, no siempre es fácil sincronizar manualmente la descripción del tipo de retorno en todos los lugares de uso.
Solución
El tipo utilitario ReturnType<T> extrae automáticamente el tipo de retorno de las funciones y puede utilizarse para tipar el resultado de la llamada a la función en cualquier parte del código. Esto reduce la cantidad de mantenimiento manual de la infraestructura de tipos y minimiza los errores relacionados con la discrepancia entre el tipo descrito y el tipo real del valor de retorno.
Ejemplo de código:
function createUser(name: string, age: number) { return { name, age, created: new Date() }; } type User = ReturnType<typeof createUser>; // User: { name: string; age: number; created: Date; }
Características clave:
¿Se puede usar ReturnType con métodos de clases?
Sí, pero es importante recordar el contexto: si el método es una propiedad de un objeto con una función, utiliza ReturnType<obj['método']>.
Ejemplo de código:
class MyClass { foo(x: number) { return x * 2; } } type FooReturn = ReturnType<MyClass['foo']>; // ¡Error de tipo! // Se necesita así: type FooReturn = ReturnType<(x: number) => number>; // number // O sacar el método como función: const obj = new MyClass(); type FooReturn2 = ReturnType<typeof obj.foo>;
¿Qué devolverá ReturnType para funciones con void/never?
Para una función con tipo declarado void, ReturnType devolverá void. Para never — never.
Ejemplo de código:
function doNothing(): void {} type Result = ReturnType<typeof doNothing>; // void
¿Funciona ReturnType con sobrecargas de funciones?
No, ReturnType extrae el tipo de retorno de la "implementación" en sí, y no de todas las sobrecargas. Si hay múltiples sobrecargas, se toma el tipo de implementación descrito.
Ejemplo de código:
function func(x: number): number; function func(x: string): string; function func(x: any): any { return x } type RT = ReturnType<typeof func>; // any
En un proyecto se declara un tipo manual para el objeto de retorno de una función. La función cambia — el tipo no se actualiza, las llamadas fallan en tiempo de ejecución.
Ventajas:
Desventajas:
Se pasa a utilizar ReturnType en todas partes donde se usa el valor devuelto por la función. En caso de cambios, el tipo siempre está actualizado.
Ventajas:
Desventajas: