Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

91
Vistas
¿Puede crear un tipo de mecanografiado que tenga exactamente una de un conjunto de propiedades Y sea indexable por ese conjunto?

Tengo los siguientes tipos:

 type OrBranch = { or: Branch[] } type AndBranch = { and: Branch[] }

Me gustaría un tipo Branch que puede ser OrBranch o AndBranch . Así que primero probé:

 type Branch = AndBrand | OrBranch

Funciona muy bien, a menos que quiera hacer algo como:

 let branch: Branch = ... let andOr = 'and'; // or 'or' let nodes = branch[andOr]

Entonces obtengo que la branch no es indexable. OK, entonces pruebo un tipo indexable:

 type AndOr = 'and' | 'or'; type Branch = Record<AndOr, Branch[]>;

Pero eso requiere que AMBOS and y or existan, por lo que no puedo lanzar AndBranch a Branch en este caso.

Similarmente

 type Branch = Record<AndOr, Branch[]> | AndBranch | OrBranch

no funciona, por la misma razón.

Si bien podría usar guardias de tipo para determinar el tipo, tengo funciones largas que operan en estos objetos, en las que pueden tratarse de la misma manera que la propiedad. Tenía la esperanza de eliminar un montón de código duplicado usando la variable andOr , que los protectores de tipo realmente no previenen. Por ejemplo:

 let retval = {} as Branch; if (isAnd(branch)) { // branch is a Branch parameter passed in (retval as AndBranch).and = [] as Branch[]; set = (retval as AndBranch).and; } else { (retval as OrBranch).or = [] as Branch[]; set = (retval as OrBranch).or; } set = _.reduce(set, (all, item: Branch)=> { if (isAnd(branch) && isAnd(item)) return _.union(all, item.and); else if (isOr(branch) && isOr(item)) return _.union(all, item.or); else return all; }, [] as Branch[]);

contra

 andOr = isAnd(branch) ? 'and' : 'or'; let retval = {} as Branch; retval[andOr] = _.reduce(set, (all, item: Branch) => { if (item[andOr]) return _.union(all, item[andOr]); else return all; }, [] as Branch[]);

Sé que hay una manera de requerir exactamente uno de and or (como la respuesta al objeto Enforce Typescript tiene exactamente una clave de un conjunto ). Pero ese tipo no es indexable.

¿Es posible obtener ambos efectos?

about 4 years ago · Juan Pablo Isaza
1 Respuestas
Responde la pregunta

0

Hacer que el tipo sea indexable no resolverá el problema básico, que es que está tratando de usar la propiedad and en algo que puede ser una rama and (y por lo tanto tener la propiedad) o puede ser una rama or (y por lo tanto no) . En su lugar, pregúntale a la rama qué tiene y úsalo, porque eso permite que TypeScript reduzca el tipo:

 if ("and" in branch) { // ...use `branch.and`... } else { // ...use `branch.or`... }

Puede combinar eso con su andOr si tiene un código que cree que sabe cuál es la rama, tal vez mediante el uso de una función de aserción de tipo:

 function assertIsAndBranch(branch: Branch): asserts branch is AndBranch { if (!("and" in branch)) { throw new Error(`branch is not an AndBranch`); } } // (And `assertIsOrBranch`)

Después:

 if (andOr === "and") { assertIsAndBranch(branch); // ...here, TypeScript knows `branch` is an `AndBranch`... }

Con respecto a su edición: si tiene un código significativo que necesita lidiar con los elementos contenidos en AndBranch and OrBranch or sin saber o preocuparse si son instancias de AndBranch u OrBranch , los rediseñaría como una unión discriminada donde todos los miembros del sindicato tienen los mismos items (o lo que sea) de propiedad:

 type OrBranch = { type: "or"; items: Branch[]; }; type AndBranch = { type: "and"; items: Branch[]; };

De esa forma, el código al que no le importa qué tipo de rama sea puede funcionar con items . El código que mostraste sería:

 const items = _.reduce(branch.items, (all, item) => { return _.union(all, item.items); }, [] as Branch[]); const retval = {type: branch.type, items};

Enlace del patio de recreo

Tener propiedades tiene una doble función (indicar el tipo de rama y los elementos dentro de ella) como lo hacen en sus tipos actuales hace que escribir código seguro para manejar los elementos sin saber/importar qué tipo de rama es realmente difícil.

about 4 years ago · Juan Pablo Isaza Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda