Some performance struggles
Hey, I seem to be having some performance issues & I'm wondering if there are more optimal ways of typing stuff out 🙂 I've added the schema I'm working with bellow, importing anything except for the inferred type really seems to make things chug
22 Replies
Looks pretty good overall! The things I'd probably change are:
- Prefer adding
?
to the key to .optional()
or ?
in the value
- You can define an index signature directly in an object like "[string]": "string | undefined"
instead of intersecting a Record.
- You can avoid using omit
by creating a base type without that property initially
In terms of the types themselves, see if you can find a way to define them that avoids intersecting with unions. It has to compute it for each branch and it can get complex quickly. So maybe in the name
case, you could add name
to those branches individually and see if that helps. It seems like the last type is where TS struggles the mostThanks for the tips 🙂 ill mess around with some variations & ts traces tomorrow and hopefully ill be able to find a "fast" solution.
Curious to see what you find! I was surprised that I could see some lag on these types despite them being relatively limited.
There are other approaches we could take to try to optimize them further but starting with this stuff first makes sense, especially if you can avoid that last intersection
Is the TS server able to cache the infered outputs? Or would providing types as in type<MyType>(...) help? 🙂 yeah these ones i can mold quite a bit, but it had me worried for a second since we have much deeper types in our system 🙂
It should be able to cache them, but definitely there's a trick you can use to get nominal types that I think especially helps in terms of readability. Would also be interesting to get some 1:1 perf comparisons on using it to see what difference it makes there
You don't want to pass the type param directly since that param is actually for the definition
Something like this
I see 🙂 alright I'll give it a good 1-2 and post any outliers if I see them.
Thanks!
Is there a way to define optional objects in line without using scopes? I've noticed a decent performance uplift when I dont instantiate types until i need them & just define them as constant objects & utility functions that build the constant objects
& is there any validation diference between something being optional or defined as [smthSchema, '|', "undefined"]? 🙂 cuz that would solve this easily 🙂
never mind...further testing shows that the performance is about equivalent 🙂
What do you mean about optional objects? The recommended syntax for optionality is:
It's definitely true though that especially if you are going to be deriving schemas from one another with stuff like Pick and Omit, you could use
type.define
to get only the standalone definitions, then use builtin operators like ...
to merge them rather than relying on the utility methods and that could save you some overhead for sure. That was one of the things I was going to recommend as a next step if you were still having issuesAh thats perfect then 🙂 ah ill check out type.define then I've simply been creating the schema objects (stuff id pass to type) and marking them as const 🙂
type.define
will definitely help there since you'll have type safety, although of course that incurs some additional overhead.
I would definitely try and see what kind of impact that has before moving to unvalidated objects though, you'd lose so much of the benefit at that point. I guess you would still get an error when you passed them to type but yeah, DX would feel roughHmm tbh I've found it pretty ok, the schema itself is good, so I find the entire thing intuitive enough 🙂 but I have yet to type everything again. Smthn was definitely wrong as with vs without defined types our tsc when from 75s to 2.6
Tho I assume a lot of bad stuff was written as I have yet to actually code review the types, for now I just commented them out and am testing strategies on a smaller scale 🙂
Hmm yeah that's very extreme. You mean just defining the definitions as standalone then passing them to types later had that much of an impact?
Yup, we werent using them yet, just had a someone in the team take a crack at rewriting about half our pure TS types to schemas
Tho a quite a few of them have basically infinite recursion + are just complex so to be expected a bit 🙂
Oh I see. Well there will definitely be inevitable overhead there then, but hopefully it could be reduced a bit with
type.define
Yup, would there also be a way of limiting recursion in say a type calling itself?
I actually don't think the recursion is very likely to be the core problem. There are ways you can do that internally but I don't think it would help in this situation
Fair enough so just the amount of branching with ands and ors?
Most of the overhead is probably just from all the extra validation + inference and especially merging objects with
and
or omit
Yeah
So some of that you could mitigate by predefining the objectsCool, will take a shot at rewriting it with .define and hopefuly that solves it 🙂 since otherwise im loving the syntax and extensibility of arktype
+ ive already written a few decent size things depending on it..so itd be quite "fun" to extract it
I hope so too! If not, I'll try to have a look at additional optimizations at some point but overall it's unlikely I'd find a 50% improvement or anything at this point
Dont worry about it we'll figure smthn out 🙂 worst case we dont define EVERY type in the system as a validator 😄 or other solutions like prebuilding the modules