A
arktype•3mo ago
mihajm

Is there a way to morph an optional value back to a required one?

the example bellow always returns a number, but is typed as {PORT?: number | undefined}
const schema = type({
PORT: ['string?', '=>', (v?: string) => parseInt(v ?? '3000')]
})
const schema = type({
PORT: ['string?', '=>', (v?: string) => parseInt(v ?? '3000')]
})
No description
12 Replies
ssalbdivad
ssalbdivad•3mo ago
In a case like this, it seems like you want a default value:
const schema = type({
PORT: "string.integer.parse = '3000'"
})
const schema = type({
PORT: "string.integer.parse = '3000'"
})
mihajm
mihajmOP•3mo ago
thats exactly what I wanted in this case thanks! though still curious about the above example, as it would be useful for parsing purposes. Thanks for the quick answer btw!
ssalbdivad
ssalbdivad•3mo ago
Broadly, there would not be a way once you have an optional key to morph that key directly into something that would make it required because the morph will never run if the key is not present, and nothing the key itself can implement can change that. You'd have to implement the morph one level up on the object itself to be able to change which keys are present without a default value
mihajm
mihajmOP•3mo ago
Ah I see what I was missing. Fair enough 🙂
ssalbdivad
ssalbdivad•3mo ago
No problem, it's definitely the kind of thing that can be tricky to wrap your head around. I know it was when I was trying to figure out how to implement it 😅 That said, once I arrived at the current behavior, it definitely felt like it was the logical way for it to behave (at least in terms of morphs not being able to alter key presence) Stuff to do with .optional() and .default(x) applying metadata that is only relevant when attached to an object is an area where I feel like some aspects of the behavior could be unintuitive, but it seems like no matter what solution I go with that will be the case I actually avoided adding .optional() for a very long time for that reason- because it convolutes things when used in a way that's not directly referenced in an object, but .default() really benefits from some syntax like that so now they both support it Defintely feels better in the standard case like "foo?": "number" where optionality belongs to the key since that mirrors the actual behavior
mihajm
mihajmOP•3mo ago
I can imagine, I have some very minor experience because I built some JsonSchema types for a form that the user can use to build a dynamic schema we did a while back. Luckily I never got to stuff like this since I never got around to implementing type safety validation for the users input (they can simply create absurd rules like a value must be above 1000 and bellow 100) 🙂
mihajm
mihajmOP•3mo ago
off topic, but this just makes me smile 🙂
No description
ssalbdivad
ssalbdivad•3mo ago
AFAIK the fact that ArkType will throw on any unsatisfiable type is actually pretty unique in the ecosystem. You can handle the non-overlapping ranges stuff as a one-off so maybe some validators do that but to know if e.g. an intersection of unions results in a satisfiable type, you need a type system like the one arktype has. Honestly was the coolest part of the whole projec to work on, a lot of really cool set theory stuff that becomes a lot more intuitive once you have to get your hands dirty a bit 😊 Haha, I'm glad you like it! It's a been a bit controversial, but I just tell people to alias it or used a named * import if they don't like it 😛 Kinda falls out of the principle of "as close to 1:1 with TS as possible" though
mihajm
mihajmOP•3mo ago
Ah sure, but as you said that would be 1 thing 🙂 that specific form takes in a JsonSchema and then defines a rule schema and N other JsonSchemas. Its basically a way of letting the user define a transform Of A -> B | C and when to do one or the other. But lucky for me the users didnt need all that because my head was exploding from the initial implementation 🙂 either way amazing job on ArkType im gonna get to creating schemas for our larger objects tomorrow so I'm in for some quick learning 😄 Btw is there a way to localize/customize the error messages?
ssalbdivad
ssalbdivad•3mo ago
There are ways to customize error messages, but the docs are a bit lacking in that regard. You can take a look at some of the tests I linked here: https://discord.com/channels/957797212103016458/1291088800793100410 Basically, by default the goal is to customize as little of the error message as needed so we can still compose it into nice messages for e.g. unions. I know some people have worked on I18n solutions externally but it's definitely still an area where I'd want to have some more concrete recommendations. IIRC someone mentioned that there are a lot of external libraries that kind of broadly handle the problem, and that just iterating over an ArkErrors result and transforming it that way might be the easiest thing rather than configuring how the message is built ahead of time? You'll have to let me know what you find/what ideas you have. The default ArkErrors result you get on failure does contain a lot of carefully crafted errors in English, but it also contains the raw data about the error code etc. so potentially you could use that to get messages for other languages
mihajm
mihajmOP•3mo ago
I see, yeah ideally id map them directly as that would be much more efficient than iterating every time. For dx usecases the messages are great, but id love to use the same validators/errors within the forms themselves which is why I ask 🙂 ill keep you posted
ssalbdivad
ssalbdivad•3mo ago
Yeah I think as is, the error message customization system can do a great job tailoring parts of the message to be used facing, but that really only works in English. Specifically if you need to support I18N you'd likely need some other approach, so let me know if you figure anything out on that front
Want results from more Discord servers?
Add your server