Me he estado golpeando la cabeza aquí y allá y no pude progresar más que esto
por ejemplo, quiero que TObject.props acepte 'href' o 'download' solo si paso TObject.name = 'a' y no si paso TObject.name = 'p'
y también, ¿cómo puedo hacer que reduxStoreType.objects acepte una matriz de TObjects, pero no necesariamente todos deben ser de un tipo como Tobjects<'a'>
por ejemplo, quiero la posibilidad de tener lo siguiente
reduxStoreType.objects = [TObject<'a'>,TObject<'p'>,TObject<'div'>...]aquí están mis interfaces
interface TagsTypes { // HTML p: React.HTMLAttributes<HTMLParagraphElement>; a: React.AnchorHTMLAttributes<HTMLAnchorElement>; form: React.FormHTMLAttributes<HTMLFormElement>; head: React.HTMLAttributes<HTMLHeadElement>; img: React.ImgHTMLAttributes<HTMLImageElement>; input: React.InputHTMLAttributes<HTMLInputElement>; span: React.HTMLAttributes<HTMLSpanElement>; button: React.ButtonHTMLAttributes<HTMLButtonElement>; div: React.HTMLAttributes<HTMLDivElement>; } interface TObject<T extends keyof TagsTypes> { width: number; height: number; name: T; props: TagsTypes[T]; innerText: string; } interface CanvasType extends HTMLDivElement {} interface reduxStoreType { canvas: CanvasType; objects: TObject<'a'>; }Reduzcamos su problema a algo más simple, resolvamos la versión más simple y luego, con suerte, puede aplicarlo a su escenario del mundo real.
Tenemos algunas formas:
type ShapeTypes = "circle" | "square" | "rectangle" | "triangle";Y podríamos expresar los objetos así (similar a su definición TObject actual):
interface Shape<Type extends ShapeTypes> { type: Type; area: number; }Pero entonces aquí está el problema. ¿Qué pasa si queremos que un círculo tenga un radio o un diámetro? Un cuadrado para tener una longitud de lado? ¿La clasificación de un triángulo?
Aquí es donde usamos una unión discriminada:
type Shape = { type: "circle"; area: number; radius: number; } | { type: "square"; area: number; side: number; } | { ... }; // moreComo puede ver ahora, cada tipo de forma tiene propiedades específicas. Aunque esto es mucho más escribir, es lo que quieres. Verás cuando los usamos así:
if (shape.type === "circle") { shape.radius // number, no errors shape.side // error! } else if (shape.type === "square") { shape.radius // error! shape.side // number, no errors } else if (...) { ... } // more if you want Y también usarlos en una matriz es tan simple como Shape[] , mientras conserva todo este tipo de información.
Si es demasiado largo para escribir todas las propiedades compartidas redundantes, crea un nuevo tipo base e interséctalo para cada miembro de la unión:
type Base = { area: number; // more properties if needed }; type Shape = { type: "circle"; radius: number; } & Base | { // ... } | { ... }; // othersEntonces, ¿cómo aplicas esto a tu caso?
Aquí hay un código para comenzar:
type TBaseObject = { // ... }; type TObject = { // ... } | { // ... }; // ... interface reduxStoreType { canvas: CanvasType; objects: TObject[]; }