En TypeScript, la tipificación correcta de this es crucial para soportar el patrón de method chaining, cuando los métodos devuelven this para llamadas consecutivas. Si no se especifica explícitamente el tipo de retorno, TypeScript asume por defecto que el objeto devuelto es una instancia de la clase actual, lo cual es incorrecto en una herencia.
Para resolver este problema se utilizan tipos polymórficos de this (polymorphic this types) a través del this devuelto:
class Builder { value: number = 0; setValue(v: number): this { this.value = v; return this; } } class AdvancedBuilder extends Builder { multiply(factor: number): this { this.value *= factor; return this; } } const b = new AdvancedBuilder().setValue(5).multiply(2); // multiply se ve correctamente
el tipo devuelto this garantiza que la cadena de métodos esté correctamente tipificada incluso para los herederos, y no solo para la clase base.
¿Se puede simplemente especificar el nombre de la clase en lugar de usar this en el tipo de retorno (por ejemplo, devolver Builder)? ¿Cómo afectará esto a las cadenas de métodos en los herederos?
Respuesta:
Si devuelves Builder en lugar de this:
class Builder { setValue(v: number): Builder { //... return this; } } class AdvancedBuilder extends Builder { multiply(factor: number): this { // ... return this; } } const a = new AdvancedBuilder().setValue(2).multiply(2); // multiply no es visible!
multiply no estará disponible después de setValue, porque setValue devolverá Builder, no AdvancedBuilder. Solo this en la firma del método mantiene la tipificación correcta en la cadena de métodos.
Historia
En el equipo de desarrollo se creó un API fluido para la construcción de configuraciones. En los métodos se devolvía el tipo de la clase base, creyendo que era una buena práctica. Después de la aparición del heredero en el API fluido, todos los métodos adicionales se volvieron invisibles después de la cadena de llamadas estándar. Resultado: hubo que refactorizar el API a this para que los clientes pudieran usar las extensiones.
Historia
En una biblioteca interna de decoradores, se devolvió explícitamente un tipo concreto de clase. Los usuarios, al utilizar los herederos, perdían acceso a nuevos métodos, recibiendo "object has no method ...". El error solo surgió al integrarse con nuevos servicios.
Historia
Un desarrollador, copiando métodos de una API antigua de C#, reescribió la cadena de métodos en TypeScript, devolviendo el nombre de la clase. En la fase de construcción todo parecía estar bien, pero en los herederos de usuario se perdían nuevos métodos. Solo una verificación estricta en tsconfig ayudó a identificar rápidamente este problema y corregirlo a this devuelto.