¿Puede un tipo de TypeScript implementar una interfaz?
Estoy aprendiendo TypeScript y quiero extender un tipo con una interfaz, he encontrado un artículo de blog que sugiere que no es posible que un tipo extienda/implemente interfaces.
Aquí hay un ejemplo de código de lo que me gustaría hacer:
interface IPet {
needsFood: boolean
}
// How I would like to use the IPet interface with a type,
type Cat implements IPet = {
needsFood: boolean,
color: string,
}
El ejemplo de código anterior da un error. 'IPet' solo se refiere a un tipo, pero se está usando como un valor aquí.
Aquí está cómo usaría la interfaz IPet con una Class, pero ¿es posible tener el mismo comportamiento con un type?
class Cat implements IPet {
needsFood: boolean;
color: string
}
¿Hay alguna manera de que pueda tener un tipo que implemente una interfaz? ¿O necesito usar una Clase si quiero usar interfaces?
Editar: Gracias por todos los comentarios chicos, he actualizado la pregunta con un ejemplo de código. Lo que realmente estoy buscando aquí es básicamente solo una respuesta sí/no sobre si es posible que un tipo de TypeScript extienda/implemente una interfaz.
Respuesta #1
La respuesta a la pregunta tal como se formuló es no, no se puede hacer esto directamente con un alias type. Una cláusula implements solo se aplica a las declaraciones de class, y una cláusula extends solo se aplica a las declaraciones de interface o class.
Por supuesto, es bastante fácil obtener una funcionalidad análoga:
Una cláusula implements en una clase solo verifica si la instancia de la clase se puede asignar al tipo declarado, y produce una advertencia del compilador si no es así; no tiene ningún efecto sobre el tipo de la instancia. Puedes hacer lo mismo con un tipo de utilidad como
type Implements<T, U extends T> = U
Entonces Implements<T, U> no tiene un efecto en el tipo resultante, U, pero dado que U está restringido a T, recibirás una advertencia si no es asignable.
Vamos a probarlo:
type Cat = Implements<IPet, {
needsFood: boolean,
color: string,
}> // okay
type Dog = Implements<IPet, {
bark(): void
}>; // error! Property 'needsFood' is missing in type '{ bark(): void; }'
Se ve bien.
Mientras tanto, se puede usar una cláusula extends para agregar miembros o restringir miembros de un tipo padre. Esto es esencialmente lo mismo que un tipo de intersección, por lo que podemos crear un tipo de utilidad para capturar esto:
type Extends<T, U extends Pick<T, keyof T & keyof U>> =
T & U;
Aquí combinamos tanto el tipo padre T como los nuevos miembros U. He restringido U para asegurarme de que no se puedan agregar propiedades conflictivas, lo cual es similar a lo que ocurre si intentas extender una interfaz con propiedades conflictivas:
type Cat2 = Extends<IPet, {
color: string
}>
type Dog2 = Extends<IPet, {
needsFood: number // error!
}>; // error!
// Type '{ needsFood: number; }' does not satisfy the constraint Pick<IPet, "needsFood">.
También se ve bien.
Esos enfoques no son completamente idénticos a las cláusulas implements/extends, pero deberían ser lo suficientemente cercanos para muchos casos de uso. Casi seguro que existen casos límite donde difieren y es posible que estos puedan ser reparados o solucionados. Pero la conclusión básica aquí es que puedes usar restricciones genéricas y tipos de intersección para construir una solución.
Enlace de Playground al código
Respuesta #2
En TypeScript, de hecho puedes extender un tipo con una interfaz. La sintaxis para extender un tipo con una interfaz es usando la palabra clave extends. Aquí tienes un ejemplo:
interface Shape {
color: string;
}
type Square = Shape & {
sideLength: number;
}
let square: Square = {
color: "blue",
sideLength: 10
};
Esto crea un nuevo tipo Cuadrado que extiende la interfaz Shape con una propiedad adicional sideLength. También puedes usar interfaces con clases para definir la forma de las instancias de la clase. Las clases en TypeScript pueden implementar interfaces para garantizar que la clase cumpla con la estructura definida por la interfaz.
Entonces, puedes usar tanto tipos como clases para trabajar con interfaces en TypeScript.
