How to choose "one of" in a type?

Hi there!
export const user_find_one_controller_input = type({
"_id?": userApi.schema.user.get("_id"),
"_email?": userApi.schema.user.get("email")
});
export const user_find_one_controller_input = type({
"_id?": userApi.schema.user.get("_id"),
"_email?": userApi.schema.user.get("email")
});
For example here I am wanting to have either or as an object. So saying that if there is no _id then there has to be an "email" and visa versa. Not sure how to achieve this Thanks!
15 Replies
ssalbdivad
ssalbdivad5d ago
Can you use a union like type({ id: "string" }).or({ email: "string" })?
CodingWithLuke
CodingWithLukeOP5d ago
Yeah not a bad shout. Wasn't sure if there was a different way to do it. But that should work
ssalbdivad
ssalbdivad5d ago
Yeah, that is the best way to do it in a structural type system like TS/ArkType. Initially the idea of some builtin conditional property syntax is intuitive, but really it's just a different and often more convoluted way to write a union
CodingWithLuke
CodingWithLukeOP5d ago
Agreed thanks for quick input One issue may have with union:
ParseError: An unordered union of a type including a morph and a type with overlapping input is indeterminate:
Left: { _id: {} | (In: string) => Out<unknown> }
Right: { email: string }
ParseError: An unordered union of a type including a morph and a type with overlapping input is indeterminate:
Left: { _id: {} | (In: string) => Out<unknown> }
Right: { email: string }
type({_id: objectId}).or({email: "string"})
type({_id: objectId}).or({email: "string"})
Cause I do a custom Arktype that does some pipe stuff. The error makes sense what it is saying though. Just not 100% sure best approach.
ssalbdivad
ssalbdivad5d ago
Are the properties ever both specified or always one or the other?
CodingWithLuke
CodingWithLukeOP5d ago
In this case its one or the other. Its like a query that you can choose what you want to search with
ssalbdivad
ssalbdivad5d ago
{ _id: "string", "_email?": "never"} | { "_id?": "never", _email: "string" } Technically you only need to add never to one or the other, but if you want it enforced that way on both
CodingWithLuke
CodingWithLukeOP5d ago
Does it matter that technically _id is not actually a string but a morphed type?
ssalbdivad
ssalbdivad5d ago
No that will fix it Because it makes the inputs not overlapping- we will know the intersection of the input of the morph and never is unsatisfiable
CodingWithLuke
CodingWithLukeOP5d ago
Yeah thats got it Cool makes sense
ssalbdivad
ssalbdivad5d ago
If in the future you have some very complex relationships you want to check in a case like this, you can always fall back to using .narrow after the base shape has been valdiated
CodingWithLuke
CodingWithLukeOP5d ago
Sweet will keep that in mind.
ssalbdivad
ssalbdivad5d ago
Generally best to avoid making your unions to complex when you can check the base shape and then just write whatever logic you want to check those properties
CodingWithLuke
CodingWithLukeOP5d ago
Yeah in this case it was fairly straight forward but good to know either way
ssalbdivad
ssalbdivad5d ago
But for a case like this, definitely adding a single ? never is cleaner

Did you find this page helpful?