Typescript: Acortando la Declaración de Clases Simples
Tengo un patrón de código en TS que encuentro muy útil pero es extremadamente no DRY. ¿Alguna idea de cómo solucionarlo?
Me gusta “vincular” una interface
de TS con una declaración de class
. De esta manera tengo la ventaja de tener una estructura de datos simple con tipado y herencia, Y puedo realizar fácilmente comprobaciones de tipo en tiempo de ejecución con el operador instanceof
(que me permite evitar los predicados de tipo, que considero inseguros).
Para ver un ejemplo, consulta el siguiente código donde tengo una clase Doctor
que extiende una clase base Person
interface PersonInterface {
id: number
name: string
surname: string
}
class Person implements PersonInterface {
id: number
name: string
surname: string
constructor(arg: PersonInterface) {
this.id = arg.id
this.name = arg.name
this.surname = arg.surname
}
}
interface DoctorInterface extends PersonInterface {
degree: string
salary: number
}
class Doctor extends Person implements DoctorInterface {
degree: string
salary: number
constructor(arg: DoctorInterface) {
super(arg)
this.degree = arg.degree
this.salary = arg.salary
}
}
const doc = new Doctor({
id: 111,
name: 'John',
surname: 'Johnson',
degree: 'PHD',
salary: 100000,
})
console.log(doc instanceof Person) // true
console.log(doc instanceof Doctor) // true
Todo funciona, la comprobación de tipos es fácil y mi IntelliSense está contento. Todo genial. Pero como puedes ver, estoy repitiendo el código 3 veces para cada clase. Una vez para declarar la interface
, otra vez para implementarla en la class
y una final para aplicar el constructor
.
¿No hay una forma más concisa? En un proyecto grande esto se vuelve horrible de ver.
IMPORTANTE
No necesito tener métodos en mis clases. Solo se utilizan para representar datos, no comportamiento (de hecho los estoy utilizando para poblar una tienda vuex).
davy.ai
Sí, hay una forma más concisa de lograr el mismo resultado sin repetirse varias veces. Puede utilizar la sintaxis de
class
de TypeScript en combinación coninterface
para definir un patrón de código más simple y limpio.Aquí tienes un ejemplo:
En este ejemplo, estamos utilizando el modificador
public
de TypeScript en los parámetros delconstructor
, lo cual define automáticamente las propiedades de la clase. También podemos pasar elPersonInterface
como parámetro al constructor deDoctor
y usarlo para llamar al constructorsuper
enPerson
.Al hacer esto, logramos la misma estructura de datos y verificación de tipos sin repetirnos con la declaración de
interface
,class
e implementación deconstructor
.Este enfoque cumple con el principio DRY y es más fácil de leer y mantener.