Structure Node hinder DeepPartial
Hey, just stumbled across this amazing community and thought you might be able to help me. i was using a modified version of the deepPartial Function, that has been posted here
https://discord.com/channels/957797212103016458/957804102685982740/1348929382261067777
I have stumbled into an issue with certain type definitions:
while traversing the existing Loans node i come across an intersection that has no props. Although the Index still lies ahead.
now i am wondering, if my approach is wrong. while looking through the repo, i saw, that a structure only has props, if it has children that are optional or required. Maybe that is the source.
13 Replies
@Carl_c24 Ahh okay yes index signatures are not properties and can't really be made optional in a pure sense.
If the version you worked on handles your use case well that's great- it looks like you went pretty deep into the type system to get everything working 🤓 🎉
Sadly it does not, as of now it just fails to go deeper. That is why i am looking for a different way to reach those nodes. Any ideas?
This is getting into pretty complex territory with manipulating the internal structure of the type system.
I don't have time to write the whole thing for you, but I would check out this method which we use internally for recursive transformations like this:
https://github.com/arktypeio/arktype/blob/2ebcfce89aa071f06322fd4249cb78cc1602a457/ark/schema/node.ts#L492
You can access it like
myType.internal.transform
.
Then you would want to write a rule that recurses looking for structure nodes, which could convert all the required props on that node to optional props while also maintaining the existing index signatures/sequences.thanks a lot, i will try this approach and look how far i get.
I am just a bit confused as to the form of the mapper i shall provide.
this is the solution i came up with so far, it seems to be working as intended, but runs into parserErrors on a union of two branches.
Thank you for pointing me in the direction of the internal.transform. That was quite the interesting deep dive, but sadly i am back to being clueless.
could this be the same issue as here:
https://discord.com/channels/957797212103016458/1410375271483179039/1410375271483179039
@ssalbdivad
Can you help me?
Hey, I think I have the same problem, is there any progress with this? @Carl_c24 @ArkDavid
@linus.eing
i tried a bunch of different stuff, but sadly i haven't gotten it to work yet. I am a bit confused about the internal Resolution of the Union Nodes.
No luck so far, was hoping for pointers from @ArkDavid
@Carl_c24 can you post a full repro with the transform you wrote, the types you're using it on and the expected/actual output?
Could be a playground link but as long as there is no missing code I will take a look:
https://arktype.io/playground
Thanks a lot for revisiting the issue. i tried to write out all relevant bits in the playground, but it doesn't like me defining typescript types.
i placed the same code in my specs and it runs, there, so i hope you don't have too many issues running it.
The intention in this is, to allow a form to be submitted in an incomplete state, while still transforming the values and handeling all that good stuff. to determine, which fields have to remain required, we use discriminator hints, but i honestly would just hope for the optionalize to work. We can determine the specific behaviour based on the key of a prop later.
Thanks again @ArkDavid
@Carlc24 What you wrote looks pretty close, here is the version I landed on:
```ts
function applyDeepPartialSchemaRules<o extends type<object | null | undefined>>(
o: o
): type<RecursivePartial<o["t"]> | null | undefined>
function applyDeepPartialSchemaRules(
o: type<Record<string, unknown> | unknown[]>
): unknown {
const transformed = o.internal.transform(
(kind, inner, ctx) => {
if (kind == "structure" && "required" in inner) {
const optional: Prop.Schema[] =
inner.optional ? [...inner.optional] : []
if (inner.required) {
optional.push(...inner.required.map( => _.inner))
}
return { ...inner, optional, required: [] }
}
return inner
},
{ shouldTransform: (node, ctx) => node.includesTransform }
)
return transformed
}
```
The error you get currently is because of this (see the note under unions):
https://arktype.io/docs/expressions#union
This wasn't occuring when all the properties were required because we could reliably tell them apart. You could either add a required descriminator back in or use something undeclaredKeys to specify that extra keys should be rejected which would also distinguish your branches and allow this expression:
https://arktype.io/docs/objects#properties-undeclared
You are an absolute wizard. Thank you so much. i managed to make it work like this:
i am using discriminator hints. I don't know why, but the metainformation is not provided to the structure node, so i have to stop a level above that and take it from the parent of the structure node. But alas, it works and it works great.
Thanks a lot @ssalbdivad
Awesome, glad I could help!