Me encontré con un problema al escribir componentes de React con el que nunca me había topado antes. He simplificado el problema a continuación.
interface Circle { kind?: "circle"; radius: number; } interface Square { kind: "square"; sideLength: number; } type Shape = Circle | Square; const shape: Shape = { sideLength: 7, radius: 7, };Enlace a TypeScript Playground que contiene lo anterior
En el ejemplo anterior, esperaría que la declaración de la variable de shape arroje un error en TypeScript ya que ni un círculo ni un cuadrado tienen una sideLength y un radius . El objeto definido no es ni un Círculo ni un Cuadrado, por lo que, en mi opinión, no debería ser una forma válida.
¿Es posible definir los tipos de tal manera que los siguientes elementos sean válidos o errores (como se indica en la etiqueta)?
// Valid const shape: Shape = { kind: 'circle', radius: 7, }; // Valid const shape: Shape = { radius: 7, }; // Valid const shape: Shape = { kind: 'square', sideLength: 7, }; // Error const shape: Shape = { sideLength: 7, radius: 7, }; // Error const shape: Shape = { sideLength: 7, }; // Error const shape: Shape = { kind: 'square', radius: 7, }; // Error const shape: Shape = { kind: 'circle', sideLength: 7, };EDITAR:
Para mayor aclaración, en mi caso de uso kind es opcional en un círculo. Para aquellos familiarizados con React, el problema real que estoy tratando de resolver tiene que ver con la propiedad as expuesta por los componentes con estilo. Quiero que un componente acepte un accesorio opcional as permitirá al usuario cambiar el componente (por defecto, un button ) a un enlace ( a ). Si el usuario especifica as="a" , entonces quiero que TypeScript se comunique si el usuario intenta usar accesorios específicos de botones en lo que ahora es un enlace ( disabled , por ejemplo). El as prop es opcional ya que no quiero que todos los implementadores deban aprobarlo. En mi ejemplo simplificado anterior as es análogo a kind , por lo tanto, kind es opcional.
Tenga en cuenta que ha definido la propiedad de kind como una propiedad opcional, por lo que si crea un objeto de forma con solo la propiedad de radius , el circle sigue siendo válido:
Mira este objeto
const shape: Shape = { sideLength: 7, radius: 7, };Este es un círculo válido con una propiedad adicional.
Entonces, para generar un error en algún caso que haya dicho, debe hacer que la propiedad kind sea una propiedad requerida:
interface Circle { kind: "circle"; radius: number; } interface Square { kind: "square"; sideLength: number; } type Shape = Circle | Square; const shape2: Shape = { radius: 7,//Error };