Typescript build fails with large number of columns

I have a table with ~460 columns, and on trying to run typescript on my app, I'm getting "error TS2589: Type instantiation is excessively deep and possibly infinite." It goes away once I reduce the number of columns in the Drizzle mysqlTable call to <= 357. Is there any way to address this?
123 Replies
Dan
Dan2y ago
why would you have 460 columns on a table....
Luxaritas
LuxaritasOP2y ago
I can also get it to fail by adding complexity to column definitions, eg with that 357 columns it goes back to failing if I add .notNull().primaryKey().autoincrement() on the last column Not by choice! Legacy DB schema It should really be taking advantage of JSON columns as it's relatively sparse, but this is coming from a 10 year old application that was originally running on like mysql 5.5 and Drupal... NB: This is storing experimental data from a research project, where various experiments have had a lot of different types of data points I don't want to migrate it to something different now, as I'm trying to keep things backwards compatible with our legacy system
Dan
Dan2y ago
Honestly, I'm not sure if it even can be resolved at the current stage - the type inference is simply too much for TypeScript to handle. Theoretically, we could make it easier for TS by asserting some intermediate types, but that's not implemented in the current API. What you can TRY to do is describe it partially with views But that will still only work for selects, since we don't have anything else for views
Luxaritas
LuxaritasOP2y ago
Strictly speaking, I can just omit this model since I've been using some lightweight raw SQL anyways, but this still seems like a problematic failure mode IE, if you introspect a large table, you're just left with a broken project
Dan
Dan2y ago
How did you work with this table before you tried Drizzle?
Luxaritas
LuxaritasOP2y ago
Even with ~200 columns, intellisense grinds to a halt And I know that there are schemas in eg enterprise software that get that large
How did you work with this table before you tried Drizzle?
Raw SQL in PHP 🙂 And in the more recent term, Prisma (works fine, though they do a lot more pre-processing in their types)
Dan
Dan2y ago
Yes, they basically codegen all the types and the client Whereas we do everything via inferring, which puts a lot more pressure on TS
Luxaritas
LuxaritasOP2y ago
Looking at the way the Drizzle schema builder is set up, it seems like a looooot of layers of indirection
Dan
Dan2y ago
yeah, the types are pretty complex to infer everything properly
Luxaritas
LuxaritasOP2y ago
eg looking at a column definition, there's 7 exports Though I guess a bunch of that is builder alias vs builder vs concrete class and config types
Dan
Dan2y ago
Let me try to test some simple type assertion API and check if it'll help
Luxaritas
LuxaritasOP2y ago
I'd be interested to see additional details about how the types are currently intended to work - looking at it now, I'm getting a bit lost Specifically column and column builder
Dan
Dan2y ago
Hmm, I've tried building a table with 500 columns, and not seeing the error. Which column types are you using? I've tried using 500 int columns
Luxaritas
LuxaritasOP2y ago
double For most of them And a couple dozen varchar, int, and bigint What ts version are you using btw? This project is still on 4.9.5, maybe there's been improvements if you're using 5.x?
Dan
Dan2y ago
5.0.3 Well, I changed a bunch of columns to varchar, int and bigint, still no error I now have 1000 columns in the table
Dan
Dan2y ago
Luxaritas
LuxaritasOP2y ago
Updated to ts 5 and it's no longer failing
Dan
Dan2y ago
amazing
Luxaritas
LuxaritasOP2y ago
The intellisense still takes a couple minutes to kick in But it at least doesn't outright error
Dan
Dan2y ago
Well, now it depends on how powerful your PC is 🙂
Luxaritas
LuxaritasOP2y ago
I'd be curious to know what part of this is actually causing the issue
Dan
Dan2y ago
I think TypeScript provides some tracing utilities For type checking
Luxaritas
LuxaritasOP2y ago
phew - going from ~10 columns to ~250 columns, the diagnostics show something like an additional 200,000 types being created
Luxaritas
LuxaritasOP2y ago
GitHub
Slow compilation likely caused by too many types · Issue #39678 · m...
TypeScript Version: >= 3.7.5 (reproduceable in @latest and @next) Search Terms: slow compilation typecheck types typecount After refactoring the model of our project to rely more heavily in clas...
Luxaritas
LuxaritasOP2y ago
GitHub
Slow compilation likely caused by too many types · Issue #39678 · m...
TypeScript Version: >= 3.7.5 (reproduceable in @latest and @next) Search Terms: slow compilation typecheck types typecount After refactoring the model of our project to rely more heavily in clas...
Dan
Dan2y ago
hmm, interesting we do use Pick and Omit in some places
Luxaritas
LuxaritasOP2y ago
One thing that seems very useful to note If all the columns are named identically, there is no type explosion This is fine
foo: varchar('foo', {"length":191}),
foo1: varchar('foo', {"length":191}),
...
foo: varchar('foo', {"length":191}),
foo1: varchar('foo', {"length":191}),
...
This is not
foo: varchar('foo', {"length":191}),
foo1: varchar('foo1', {"length":191}),
...
foo: varchar('foo', {"length":191}),
foo1: varchar('foo1', {"length":191}),
...
I assume typescript would normally de-duplicate types, but because this changes each column type, it can't do any short-circuiting Looks like when the columns are identical, it adds ~4 types. When I change the name, it adds ~888 types The added types also show up when adding columns to different tables. Presumably the error I was getting in 4.9 had something to do with the number of types that had to be evaluated on a singular object, but the slowdown issue still winds up being an issue when taking into account the total number of columns in your schema across all tables With some ~400 colums across 50 models, it takes ~10 seconds for intellisense to kick in after a change. ~350k types. 26 seconds and ~425k types when I have ~450 split across two models.
Dan
Dan2y ago
That's a lot. I'll add an item to backlog to investigate the performance issues. Thanks for the report!
Luxaritas
LuxaritasOP2y ago
I'm wondering, is the original column name in the generated types actually used anywhere? If not, just making it string instead of extending from string would resolve a large majority of the issues
Dan
Dan2y ago
you mean the DB column name? yes, it's used for Knex/Kysely adapters, since those require DB names
Luxaritas
LuxaritasOP2y ago
Ah!
Dan
Dan2y ago
had to specifically add it for them 🙂
Luxaritas
LuxaritasOP2y ago
Makes sense
Dan
Dan2y ago
There's a lot of type transformation going on in the column builder, when you invoke the chain methods I'll probably need to look into it in the first place The current iteration of those types is a balance between the internal types convenience and the load on TS compiler But the most heavy type magic I think happens in joins It's easily the most complex place in the whole ORM
Luxaritas
LuxaritasOP2y ago
BTW what does HKT stand for? I keep seeing it in the type but it's not clear what it stands for
Dan
Dan2y ago
higher-kinded types a concept from FP that's not yet properly implemented in TS in our case, it's used to allow changing the generics on a certain type without knowing what exactly type that is so that if you have a PgIntegerBuilder and you invoke .notNull on it, which is defined way down on the base ColumnBuilder class, you'll be able to change the generics and still keep the type as PgIntegerBuilder and not ColumnBuilder
Luxaritas
LuxaritasOP2y ago
That's a good example I get the idea in theory, but the amount of things going on here admittedly make my head spin a little 🙂
Dan
Dan2y ago
same here, and I wrote the thing
Luxaritas
LuxaritasOP2y ago
😄 I have to wonder, how much simpler would this be if you just used class instances instead of the builders?
Dan
Dan2y ago
but builders are class instances you just create them via calling a function instead of new if you check the code for any one of them, all they do is create a class instance and return it
Luxaritas
LuxaritasOP2y ago
Right, but you have to construct the resulting type based on chained methods, vs a single consturctor parameter
Dan
Dan2y ago
ah I see, so get rid of chaining yes, that might simplify the types, but it'll make the API look worse IMO
Luxaritas
LuxaritasOP2y ago
Yeah I agree the chaining is elegant
Dan
Dan2y ago
chaining looks much nicer and resembles SQL we also have plans to get rid of the required DB name as 1st argument, which will make it look even nicer
Luxaritas
LuxaritasOP2y ago
Yes, I saw that fwiw, I think it matters less in the schema definition than it does in the queries themselves
Dan
Dan2y ago
true you write your schema once but it's still nice
Luxaritas
LuxaritasOP2y ago
I don't disagree!
Dan
Dan2y ago
schema definition is the 1st thing you do, it's like a first impression
Luxaritas
LuxaritasOP2y ago
On the same token: - What is the readability or usability benefit of .notNull() vs {notNull: true}? - Wouldn’t it be significantly easier to maintain with a non-builder config, since you could go from ~7 classes/interfaces per column to ~2 and avoid a large amount of type operations? - I imagine the perf issues would be largely solved due to the significantly lowered number of intermediate types That said, I realize I’m a bit out of my depth not having a deep knowledge of the implementation, so take it with a grain of salt Spent a little time trying to work through it myself to see if I could simplify with the builder pattern, and I'm following a bit more why it's as complex as it is. Unfortunate price for polymorphic builders that modify types While I don’t find the tradeoff worthwhile, ultimately it’s not up to me. Could probably be improved with some additional docs
Dan
Dan2y ago
The main reason for the chain syntax was SQL-likeness integer('id').notNull().default(0) -> id integer not null default 0
Luxaritas
LuxaritasOP2y ago
Vs { name: 'id', notNull: true, default: 0 } I guess it is slightly
Dan
Dan2y ago
Good point Another thing that the chain syntax allows is to modify the column builder in different places For example, create it in some factory and further customize in other place
Luxaritas
LuxaritasOP2y ago
In that case you’d probably rely on spread syntax or such But maybe slightly less ergonomic
Dan
Dan2y ago
Not really, since then you'll have to pass those additional properties into the factory instead of calling them after the factory returned the result
Luxaritas
LuxaritasOP2y ago
Not necessarily Consider:
const int = new Integer({…getBaseProps(), notNull: true })
const int = new Integer({…getBaseProps(), notNull: true })
Where getBaseProps is typed to return IntConfig
Dan
Dan2y ago
ok, this is the "props factory" then, instead of the column builder factory yeah, that might work but it doesn't look as nice as the chain syntax, still 🙂
Luxaritas
LuxaritasOP2y ago
As I said, it’s ultimately not up to me But it seems like you’re adding a lot of complexity for a marginal readability benefit
Dan
Dan2y ago
well, it's all different parts of DX both the syntax and type complexity
Luxaritas
LuxaritasOP2y ago
Yep
Dan
Dan2y ago
thanks for the suggestions though! it's always good to get a side opinion.
Luxaritas
LuxaritasOP2y ago
I personally find the props version just as usable, but that’s just my opinion I’ve been trying to play to see if there’s a way to get the builder implementation to be less complex, but building types with polymorphic builders is really hard
Dan
Dan2y ago
yep
Luxaritas
LuxaritasOP2y ago
As I’m sure you well know. My hubris thought otherwise lol
Dan
Dan2y ago
we might consider improving things there, but currently have more important stuff to implement
Luxaritas
LuxaritasOP2y ago
Sure
Luxaritas
LuxaritasOP2y ago
It uses functions returning raw objects instead of classes to get around the need to have a polymorphic reference to the subclass It's possible there may be a way to simplify it further, but this is as far as I got right now
alexblokh
alexblokh2y ago
wow, what a thread
Luxaritas
LuxaritasOP2y ago
Sorry, interesting technical problem got the better of me 😅 Yeah want to follow up on this again - even omitting that large DB model, intellisense is really slow once I start importing from the schema file Like, "I hit . and it takes 10 seconds to see results" slow. It's a huge productivity killer What I'm doing in the meantime is when generating my schema, setting the column name type parameters to 'string'
Cayter
Cayter2y ago
Is there a way to workaround this? I tried migrating our production code with pg that has 26 tables and 14 columns each on average, the intellisense is taking up to 5s to show, would be great if there is a temporary solution
Luxaritas
LuxaritasOP2y ago
Temporary solution is to pass string as the generic parameter for the column name
rphlmr ⚡
rphlmr ⚡2y ago
Generic seems hard to work for certain column type helpers (like text), but as string seems ok. Thanks, will also try your solution.
id: uuid("id" as string).primaryKey(),
phoneNumber: text("phone_number" as string).notNull(),
id: uuid("id" as string).primaryKey(),
phoneNumber: text("phone_number" as string).notNull(),
Cayter
Cayter2y ago
hmmm doesn't seem to work though... my intelisense is still very slow >.<" ok, i tried switching to webstorm from vscode, the intellisense is by worst up to ~1.5s only
Andrii Sherman
still a lot, but better we will improve types to make typescript work faster with it. It's not something we are going to work right now, but it's a priority for us
Cayter
Cayter2y ago
my team tried out vim, instant intellisense, so it's vscode doing some stuffs behind the scene, we also tried disabling vscode extensions and re-enabled 1 by 1, it was still very slow
Dan
Dan2y ago
another point to vim I wish I could use it without breaking my fingers and remembering which button to press
Andrii Sherman
oh, that's actually great feedback
Cayter
Cayter2y ago
here's the vim recording
Dan
Dan2y ago
amazing
Andrii Sherman
wow we can make a banner in docs "Use Vim to make intellisense instant"
Luxaritas
LuxaritasOP2y ago
I’m incredibly surprised, I don’t know what would make it faster in VIM, I was seeing noticeable slowdowns even just with running tsc
Cayter
Cayter2y ago
are you also using vscode? Ok diving deeper does allow us to understand more, it's not vim that brings the improvements, it's my team was using coc-tsserver with vim which is a fork from the official tsserver implementation, the coc-tsserver implementation seems to be faster because it doesn't have all the latest typescript features from the first look
PapaFinn
PapaFinn2y ago
I use Neovim with the built in LSP and code suggestions are instant, so it’s not just coc.
Luxaritas
LuxaritasOP2y ago
How many total columns do you have? How many files are they split between? If you only have a file with 10 columns imported, it won’t be noticeable. If you wind up having a couple hundred columns in imported files, that’s when it gets to be a slog
PapaFinn
PapaFinn2y ago
Yep, you're right! Just tested with hundreds more columns and it takes quite a long time. Not even sure how long as I never saw anything come up 😅
Cayter
Cayter2y ago
did this actually work faster for u?
rphlmr ⚡
rphlmr ⚡2y ago
Kind of (much faster than before) I can't remember the last time I wait for intellisense 😅
Cayter
Cayter2y ago
so basically just add as string to all the columns? does that break anything?
rphlmr ⚡
rphlmr ⚡2y ago
yes (if it matters, I have a M1 pro chip, maybe it compensates?)
Cayter
Cayter2y ago
i'm also using m1 pro oh crap, it really helps a lot
rphlmr ⚡
rphlmr ⚡2y ago
Daniel Rosenwasser
TypeScript
Announcing TypeScript 5.1 - TypeScript
Today we’re excited to announce the release of TypeScript 5.1! If you’re not yet familiar with TypeScript, it’s a language that builds on JavaScript by adding constructs called types. These types can describe some details about our program, and can be checked by TypeScript before they’re compiled away in order to catch possible typos,
rphlmr ⚡
rphlmr ⚡2y ago
Vscode now uses TS 5.1. Maybe it's just me but it feels betters than before 😆
Cayter
Cayter2y ago
i've been using 5.1 by configuring vscode to use node module's one, so i couldn't feel the difference between 5.0 and 5.1...
balanced.rocks
M1 Mac Pro here, Neovim running tsserver. 49 tables. 1,000 lines in schema total so say 800ish total columns. Drizzle is completely unusable. My db type defaults to any and I get 0 type recognition. When reducing the project to a single table, it works great. I haven't analyzed exactly when the types breakdown due to scale, but the size of the schema is definitely the issue.
Md Jahidul Islam milon
I have 13 tables most table with around 10-12 column i am on windows 10, with 32 gb RAM, still facing issue with code completion, suggestions, showing ts error , sometimes ts server just stoped working need to restart VSCODE. i am sharing the video https://discord.com/channels/1043890932593987624/1119853271616602203 check his thread i post a video and screenshot of my pc configuration. its really hard to maintain and work on medium label project. please fix this. its very problematic
Andrii Sherman
We are aware of this issue, and it's not something that we can fix quickly. We are experimenting with types to make them less complex and help the server function more efficiently. We are doing it meanwhile implementing new features that we see important for us and for the community We have a few things to finish in June and needed part of a July will be spent trying to make types smaller
Md Jahidul Islam milon
ok thanks for replying, but started migration our production app to drizzle , facing issue and slowing down the development. you guys did a great job please try to fix this issue as soon as you can thanks again for the great ORM
Andrii Sherman
I understand that, and I know what it's like to wait for developers to fix something that is blocking the development flow. We've been in that situation as well. 😅 Just to clarify, we are putting in our best effort to dedicate as much time as possible to improving Drizzle, both for existing and new users. However, not every day can be entirely free after our main jobs, so there may be weeks where progress is slower, while other weeks may be faster. Nevertheless, I greatly appreciate the support and patience from the community. It means a lot to us
Md Jahidul Islam milon
yeah i also appreciate your efforts
balanced.rocks
Thanks for all your effort. I'm excited to migrate over to Drizzle when it's ready whenever that may be. If you need a big schema to test realistic implementation, let me know
hachoter
hachoter2y ago
Is there any updates on this?
Dan
Dan2y ago
it's one of our priorities for this month
Dustin@WunderGraph
No pressure but I'm worried to proceed with Drizzle if the problem can't be addressed soon. Is it even fixable or does it entirely depends on TypeScript compiler? Some update would be indeed very helpful. Thank you.
Andrii Sherman
This is exactly what @Dan Kochetov is going to work on now. We will update here as soon as we have some results. We had 1 important release to prepare, which should be live soon, and this is our next top-1 priority. We are not moving forward with Drizzle features until this one is fixed, so we are fully focused on resolving it. We didn't have a chance to start working on this one earlier because we had to spend a bit more time on fixes for a release we will be dropping soon
Dustin@WunderGraph
Awesome! I'd expect you running into this issue as well with your own projects right?
Andrii Sherman
yes
Dan
Dan2y ago
we simply don't need the type checks, the compiler runs directly in the mind
Andrii Sherman
I have a production project with 77 tables, but it is using an old drizzle version (0.11.6) that is over 1.5 years old. While it still works really well in production, the data types have evolved significantly since then, and we haven't had a chance to upgrade it because everything was working well for us
Dustin@WunderGraph
Let me downgrade to 0.11.6 sweating
Andrii Sherman
if you want to see how it looked like in 0.11.6 https://drizzle.team/article/drizzleorm-v011-18-months-into-development/ 👀
Md Jahidul Islam milon
whenever got any notification from this. I just hope this issue fixed 😊
Andrii Sherman
exactly
DiamondDragon
DiamondDragon2y ago
🙏
Andrii Sherman
You can check types issue here [email protected] We've run the diagnostics on a database schema with 85 tables, 666 columns, 26 enums, 172 indexes and 133 foreign keys. We've optimized internal types which resulted in 430% speed up in IntelliSense. https://github.com/drizzle-team/drizzle-orm/releases/tag/0.28.0
Luxaritas
LuxaritasOP2y ago
Awesome! I’ll be sure to give the new version a go next week after I get back from vacation
ivanfeliciano
ivanfeliciano2y ago
TSC diagnostics types went from 106k to 81k and I only have about 8 tables, ~10 columns each. Good job, thanks!
Noahh
Noahh2y ago
just updated, and without a single change watching with tsc finishes almost instantly...this single-handedly made drizzle the obvious choice!
Andrii Sherman
Nice!
Ramazan
Ramazan2y ago
My two biggest issues with drizzle fixed in one patch, way to go lol
Andrii Sherman
🫡🫡
Cayter
Cayter2y ago
Thx, just tried upgrading it, the Intellisense speed is almost instant but can't deploy yet due to CI type check failing https://github.com/drizzle-team/drizzle-orm/issues/988
GitHub
[BUG]: drizzle-orm 0.28.0 type fails with drizzle-zod 0.5.0 · I...
What version of drizzle-orm are you using? 0.28.0 What version of drizzle-kit are you using? 0.19.12 What version of drizzle-zod are you using? 0.5.0 Describe the Bug import { type InferModel, sql ...
Andrii Sherman
cc @Dan Kochetov
Want results from more Discord servers?
Add your server