A
arktype2mo ago
TheGuy

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
ssalbdivad2mo ago
Can you use a union like type({ id: "string" }).or({ email: "string" })?
TheGuy
TheGuyOP2mo ago
Yeah not a bad shout. Wasn't sure if there was a different way to do it. But that should work
ssalbdivad
ssalbdivad2mo 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
TheGuy
TheGuyOP2mo 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
ssalbdivad2mo ago
Are the properties ever both specified or always one or the other?
TheGuy
TheGuyOP2mo ago
In this case its one or the other. Its like a query that you can choose what you want to search with
ssalbdivad
ssalbdivad2mo 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
TheGuy
TheGuyOP2mo ago
Does it matter that technically _id is not actually a string but a morphed type?
ssalbdivad
ssalbdivad2mo 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
TheGuy
TheGuyOP2mo ago
Yeah thats got it Cool makes sense
ssalbdivad
ssalbdivad2mo 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
TheGuy
TheGuyOP2mo ago
Sweet will keep that in mind.
ssalbdivad
ssalbdivad2mo 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
TheGuy
TheGuyOP2mo ago
Yeah in this case it was fairly straight forward but good to know either way
ssalbdivad
ssalbdivad2mo ago
But for a case like this, definitely adding a single ? never is cleaner

Did you find this page helpful?