Comments (6)
A good example is third party plugin or dialect that does something like this
const something = somethingImmutable as any
something.someReadonlyField = 42
return something
and then uses that somewhere else to get something done. Then people using that plugin or dialect would open issues here about some obscure bugs that plugin is causing. freeze
prevents this kind of hacking.
Also in some rare places Kysely needs to use the any
type internally to keep the code sane. For example see the parsers. They wouldn't benefit from strict types that much, but the code would become completely unreadable if we kept the DB
, TB
and the derivative types everywhere.
In these places where some things are declared as any
, things could be mutated by accident causing unpredictable side effects somewhere else.
Since Object.freeze
has absolutely no meaningful effect on performance, but makes sure on javscript engine level that nothing gets mutated, why not use it? I understand that the same is true for all other types too. You can cast a number
to any
and assign a string to it, but there's no clean way to prevent that on javascript level. If there were, I'd use it.
Also in my experience, libraries need to be as "fool proof" as possible. If there is a way to use the API the wrong way, people will find it and hack the hell out of it and then go to stackoverflow/reddit to scream how **king **it that library is when it's bugging because of the hacks.
from kysely.
As you know, readonly
is just a compile-time concept and doesn't actually guarantee anything. Performance is not an issue. I've run some simple tests and it takes around 0.012 millisecond to build and compile this query to SQL:
const qb = db
.selectFrom(['animal', 'person as p'])
.select('animal.name')
.distinctOn('p.firstName')
.whereRef('p.lastName', '=', 'animal.name')
.where('animal.name', 'in', ['foo', 'bar', 'baz'])
.whereExists((qb) =>
qb.subQuery('movie as m').whereRef('m.id', '=', 'p.id').selectAll()
)
Dropping freeze
takes that down to something like 0.010 milliseconds. Both of those numbers are meaningless compared to everything else, like executing the query and sending it to the database server. Both of which take hundreds or thousands of of times longer and are done outside of Kysely.
By using freeze
I can be sure nothing is ever mutated by accident.
from kysely.
Actually, I just ran that test again and it takes around 0.01 milliseconds with and without freeze. Object.freeze
has no effect on performance in Kysely anymore.
I ran this on a M1 macbook air and node 16.12.0.
Here's the test if you want to run it yourself:
function test() {
const qb = ctx.db
.selectFrom(['person as p', 'pet'])
.select('pet.name')
.distinctOn('p.first_name')
.whereRef('p.last_name', '=', 'pet.name')
.where('pet.name', 'in', ['foo', 'bar', 'baz'])
.whereExists((qb) =>
qb.subQuery('movie as m').whereRef('m.id', '=', 'p.id').selectAll()
)
const result = qb.compile()
}
for (let i = 0; i < 1000; ++i) {
test()
}
const N = 100000
const t0 = new Date()
for (let i = 0; i < N; ++i) {
test()
}
const t1 = new Date()
console.log(`${(t1.getTime() - t0.getTime()) / N} ms`)
from kysely.
OK, thank you!
from kysely.
I still think it's unnecessary with read-only types, but it's probably harmless, except for little DX overhead. I can't imagine a case when freezing would help. Is there a possibility kysely objects are mutated by some other library? I am just curious.
from kysely.
Thank you for such a detailed answer. I have no other question.
As for "no clean way to prevent that", there is a lib implementing newtype pattern, https://github.com/gcanti/newtype-ts, I was using it, but the ceremony with that was so annoying I switched back to branded types, which can be violated, but that's the responsibility of the developer.
Speaking of branded types, I am using io-ts a lot, so instead of a string or a number, I am using String64 or PositiveInteger etc. It's invaluable for handling untyped values from REST APIs etc.
Just for fun, that how I was trapped by fp-ts. io-ts decode returns Either, and I was furious I can not extract a value "easily" so I had to learn pipe Either map, chain, match etc. 😂
https://github.com/gcanti/io-ts/blob/master/index.md
from kysely.
Related Issues (20)
- Compile time checks for empty arrays HOT 2
- Incorrect types and missing suggestions when using object index signature HOT 2
- UUID doesn't seem to work for inserts (Postgres) HOT 1
- Loose typechecking on innerJoin/leftJoin comparisons HOT 2
- TypeChecking for doUpdateSet not working since 0.27.0 HOT 3
- Support "using" in joins
- [Q] Reusable CTE (psql) HOT 1
- Issue with parentheses in Postgres using a conflict expression HOT 1
- Query execution result type always resolves to an empty object i.e. "{}" HOT 2
- camelCase plugin is not being applied to subquery results that incorporates jsonArrayFrom HOT 3
- Streaming results not working on Deno for PostgreSQL HOT 2
- Case of extremely slow type checking HOT 4
- ParseJSONResultsPlugin HOT 1
- `INCLUDE` clause in Postgres `createIndex`
- Pass client instance HOT 3
- Inject type from join via raw sql HOT 2
- Set role & configs HOT 2
- dropTable temporary modifier
- Ms sql server - database / schema / tablename HOT 3
- Autocomplete issue with TS 5.0.2 HOT 4
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from kysely.