Thanks Sandeep.
so you're using just typescript with a query builder?
Jiri Spac, yes. It uses knex for query building. While knex is fairly robust and has type definitions, it is also not written with type-safety in mind.
However, when people define data sources, I derive the type of entities from the specified mapping:
const users = mapDataSource({
name: "User",
fields: {
id: {
type: types.number
},
name: {
type: types.string,
},
},
})
Here types.string, types.number etc. are runtime types (implemented through io-ts). The static type of User entity can be derived from the above:
type IUser = typeof users["EntityType"]
This works for complex types too as the runtime types are composable. This is outlined in more detain in the docs here. I have also blogged more about io-ts here.
So the bottom line is, even if your database column type is untyped jsonb etc. you get runtime type verification and because your GraphQL schema is also derived from them (automatically in most cases) you don't have to repeat the type definitions.
The expectation is that most of the application-level business logic will be written against well-typed POJOs. This fits well with the ideas around hexagonal architecture and ensures that application logic is not coupled with a specific model API, which has been a pain point for me in past when using ActiveRecord, mongoose etc.
However, we do have use cases when we would need to intercept queries ourselves and GRelDAL exposes interception hooks for these cases. In these cases it is possible to write type-unsafe code using Knex queries directly.
I have briefly explored on making this end-to-end type-safe but currently this is not easy to do given limitations in typescript itself, and makes the API very awkward for javascript users. This also conflicts with my parallel goal that users shouldn't have to define types themselves and in all practical cases types should by auto-inferrable.
So for now, I have settled on the trade-off that code written against Knex API directly may be unsafe. In addition the library internals have type-unsafe code. Hence both of these need to have good test coverage.
This is likely to get a lot easier in future if/when typescript adds support for forcing type inference of literal types (currently string literals are always inferred as string type) and adds user specified type variance (which flow already has).