Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

85
Views
¿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 answers
Answer question

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 Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!