TypeGraphQL

Build type-safe GraphQL APIs in TypeScript by defining schema and resolvers with classes and decorators instead of hand-written SDL.

Framework
npm
v2.0.0-rc.3
8,092stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
62/100Good
Development Activity40
Maintenance44
Community64
Maturity60
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
83/100Excellent
Architecture85
Code Quality88
Innovation78
Learning Curve80

TypeGraphQL removes the duplication that normally comes with building a GraphQL API in TypeScript: instead of writing a schema.graphql file, hand-rolled TypeScript interfaces for every type, and loosely-typed resolver functions that have to be kept in sync by hand, you define object types, inputs, queries, and mutations once as annotated classes. Decorators like @ObjectType(), @Field(), @Resolver(), @Query(), and @Mutation() describe both the runtime behavior and the GraphQL schema at the same time, so the schema is generated automatically from the classes at startup via buildSchema().

Beyond schema generation, TypeGraphQL bakes in the plumbing every non-trivial GraphQL API ends up building anyway: constructor-based dependency injection for resolver classes, an @Authorized() guard system for field- and resolver-level access control, automatic argument validation through class-validator, custom middleware pipelines, and subscription support built on graphql-yoga’s subscription helpers. Because everything is expressed as TypeScript classes, editor tooling, refactors, and the compiler catch mistakes that a hand-maintained SDL/resolver split would silently miss.

What You Get

  • Decorator-driven schema definition (@ObjectType, @InputType, @InterfaceType, @Field) that generates a GraphQL SDL schema directly from annotated TypeScript classes
  • Resolver classes (@Resolver, @Query, @Mutation, @FieldResolver, @Subscription) that read like controllers, with constructor-based dependency injection into a configurable IoC container
  • Built-in @Authorized() guards for role- and policy-based access control at the field or resolver level, with a pluggable authChecker function
  • Automatic argument validation via class-validator decorators on @ArgsType() classes, so invalid input is rejected before it reaches resolver code
  • Custom middleware support (@UseMiddleware) for cross-cutting concerns like logging, error mapping, and query-complexity limits via graphql-query-complexity
  • First-class subscriptions built on @graphql-yoga/subscription’s Repeater/pipe/filter primitives for pub/sub-based real-time fields

Common Use Cases

  • Building a GraphQL API server (with Apollo Server, graphql-yoga, or any GraphQL-over-HTTP layer) where the schema is derived from TypeScript classes instead of maintained by hand in SDL
  • Adding a typed GraphQL layer on top of an existing ORM (TypeORM, Prisma) so entity classes and GraphQL object types stay in sync as the data model evolves
  • Enforcing authorization rules (role checks, ownership checks) declaratively at the field/query level via @Authorized() rather than scattering checks through resolver bodies
  • Validating mutation/query arguments automatically using the same class-validator decorators already used elsewhere in a TypeScript codebase
  • Exposing GraphQL subscriptions for real-time features (chat, notifications, live updates) using the built-in pub/sub subscription resolvers

Under The Hood

Architecture TypeGraphQL centers on a global MetadataStorage singleton (src/metadata/metadata-storage.ts) that decorators populate as classes are loaded: @ObjectType, @Resolver, @Query, @Field, and friends each register metadata entries (queries, mutations, subscriptions, field resolvers, object/input/interface type definitions) rather than doing any work themselves. At startup, SchemaGenerator.generateFromMetadata() (src/schema/schema-generator.ts) reads that accumulated metadata and walks it to construct actual graphql-js types (GraphQLObjectType, GraphQLInputObjectType, GraphQLInterfaceType, etc.), wiring each field to a generated resolver function built by src/resolvers/create.ts. This two-phase design — declarative registration via decorators, then a single synchronous build pass — means the core abstraction that would break the most under change is MetadataStorage’s shape: every decorator and the schema generator both depend on its exact structure.

Tech Stack The library is TypeScript-only, targeting ES2021 with strict mode, experimentalDecorators, and path-mapped imports resolved via typescript-transform-paths. Runtime dependencies are deliberately minimal: graphql and class-validator are peer dependencies (so consumers control their exact versions), @graphql-yoga/subscription supplies the async-iterator primitives for subscriptions, and graphql-query-complexity is bundled for complexity-based rate limiting. It ships dual CJS/ESM builds (tsconfig.cjs.json / tsconfig.esm.json) plus a separate typings build, assembled by a custom scripts/package.json.ts post-build step.

Code Quality The project has an extensive functional test suite under tests/functional/ (30+ spec files covering authorization, middlewares, interfaces, generics, directives, subscriptions, and more) run through ts-jest with a dedicated tests/tsconfig.json, plus a tests/helpers directory of shared test scaffolding. Static analysis is layered: ESLint with a large custom .eslintrc, Prettier formatting, cspell spell-checking, and markdownlint for docs, all wired into a pre-commit hook via Husky and lint-staged. GitHub Actions runs a dedicated check.yml workflow (type-checking across CJS/ESM/tests/examples/benchmarks configs, lint, format, spell-check) alongside a separate CodeQL security workflow, indicating a mature CI gate rather than a single generic test job.

What Makes It Unique TypeGraphQL’s distinguishing choice is treating the TypeScript class itself as the sole schema authority — competing approaches either hand-write SDL and generate types from it (schema-first, e.g. GraphQL Code Generator) or hand-write resolvers alongside a separately maintained SDL file. TypeGraphQL instead derives the SDL from decorated classes at runtime, so a single edit to a class field automatically propagates to the schema, the resolver’s TypeScript types, and (via class-validator) argument validation — collapsing three normally-separate artifacts into one, at the cost of relying on experimental decorator metadata rather than pure standard TypeScript.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search