[1] https://github.com/phiresky/ts-typed-sql [2] https://github.com/Ff00ff/mammoth [3] https://github.com/AnyhowStep/tsql [4] https://github.com/travigd/vulcyn
A query in one of those looks like the following:
const rows = await select(list.id, list.createdAt)
.from(list)
.where(list.createdAt.gt(now().minus(`2 days`)).or(list.value.eq(0)))
.limit(10);
The resulting type of `rows` is inferred by TypeScript to the corresponding correct type (`{id: string, createdAt: Date}`)Prisma solves the problem by generating code, while all of these do it completely in type-level within typescript. Prisma also seems to introduce its own query language, while the above linked libraries stay closer to SQL.
[1] was written by a friend of mine and I'm using it in production to great success. I wouldn't recommend it though because it has repeatedly broken with new TypeScript updates since it uses very complex type structures and the dev has basically given up on it due to the complexity.
[2] is probably the most production-ready, though it has some design choices I'm not sure about.
[3] is the most well-designed, and can handle complex scenarios (including differentiating between join types etc). But it's incomplete so far.
[4] I have not used.
Pure type-level has the advantage of not adding a compile-step and keeping everything in a tool you already know. But all of the above have the disadvantage that the resulting type structures are very complex - most TS devs would have a hard time understanding the internals of the libraries and the resulting type errors can be unreadable. They can also cause the TS compiler to slow down significantly (in the past [1] had exponential compile time when adding a new column, though this has been fixed).
Also, since the TS compiler uses heuristics in multiple places and the type system is not sound, Microsoft has introduced regressions that have broken [1] in every other release.