Strict typing with TS
See original GitHub issueThis issue is to track a set of goals for type safety in TypeScript. In experiments, I have confirmed that all of these should be possible. While the increased verboseness has some ergonomic cost, the resulting type safety is overwhelmingly worth it in my opinion.
Object Types
For every field of a GraphQLObjectType, the resolver (including a “default resolver”) must return a value compatible with the “source” of the field’s GraphQL “type”. For example, if ChildType expects { foo: string }, then the result of ParentType’s child field cannot be { foo: 123 } or "foo".
Arguments & Input Types
The configuration of all defined arguments and input types must be checked against the types used in a resolver. For example, a resolver expecting args.foo to be a non-null string cannot be used in a field that defines argument foo as optional.
Scalars
The memory type of both custom and built-in scalars must be tracked. For example, a field with an argument configuration describing foo as a GraphQLString cannot have a resolver that expects foo to be a boolean.
Using generics and conditional types, I have been able to demonstrate that each of these is possible. However, as these effect the type signature of all primitive GraphQL components, there are a substantial number of changes across the repo. At one point I had opened a PR to DefinitelyTyped that gave partial support for strict typing of arguments, but the change was breaking (from the perspective of types) and I was too busy to effectively convey the significance before the PR was auto-closed.
As this is a natural time to implement this kind of change (during an existing push to re-type the whole codebase), I’m going to open a PR that converts the entire repo to TS in a way that accomplishes these goals. I’ll begin my changes as soon as #2139 gets merged and there’s a feature lock for 15.
Issue Analytics
- State:
- Created 4 years ago
- Reactions:22
- Comments:16 (7 by maintainers)

Top Related StackOverflow Question
As a tiny demonstration of one piece of this, consider this partial TS reimplementation of the graphql-js codebase:
Using this, it’s perfectly legal to create the following
Persontype:However, if we change the
ageresolver to return a string, our TypeScript will report an error, and prevent us from ever shipping bad code!Definitely 😄
This is my take too. I began implementing the strong types I proposed above in a refactor to TS… but the number of changes were truly overwhelming, and impossible for any reviewer to track. Instead, I decided to wait on this heroic undertaking to land. The goal there was to migrate the codebase while minimally changing its public TS interface. Once this is complete and merged, I plan on conducting a substantial overhaul of these types to enable the kind of functionality I described above.