background: I have a NodeJS project that’s currently written in JavaScript and I’m converting it to be TypeScript. I’m trying to make things type-safe, from database logic to application logic.
My database layer in JavaScript uses knex.js + Objection.js. I’m moving to Kysely for less overhead/more type safety along with the TypeScript conversion. Since this project is kind of large already, I’m doing an incremental conversion, and both systems will stay in the codebase until I rewrite enough of the core application and tooling.
So - what’s the problem? I use BigInts in a few places. I can get them from the database as strings:
createPool({
// ...
supportBigNumbers: true,
bigNumberStrings: true,
})
This is “fine,” I just have to explicitly convert them with BigInt(foobar)
everywhere. This code clutter isn’t ideal but it worked, and it prevents issues at runtime if I need to do any math or comparisons.
However, I wanted to make this more type-safe at runtime and compile-time. I want my database layer to return BigInt
types in my models now that I’m moving to TypeScript.
After a couple hours of different ideas, I discovered you can add your own logic in a typeCast
callback:
createPool({
// ...
supportBigNumbers: true,
bigNumberStrings: true,
typeCast: (field, next) => {
if (field.type === 'LONGLONG') {
const value = field.string();
return (value === null) ? null : BigInt(value);
}
return next();
}
})
This connection passes into Knex+Objection.js and Kysely, and I can now get BigInt
types in my models.
P.S. I also tried Prisma (full blown ORM) but it doesn’t support the full range of unsigned BigInts yet. I did decide to keep prisma’s schema format, and I use prisma-kysely to generate types for Kysely.