npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

gql-typed

v0.0.0

Published

GraphQL schema builder with full static typing in TypeScript

Downloads

10

Readme

gql-typed - Strongly typed GraphQL

WORK IN PROGRESS: Not tested heavily yet, Type-level validation is not yet implemented.

Motivation

When building GraphQL APIs in TypeScript, it’s easy to end up with runtime-only type safety—your TypeScript code might compile just fine, but at runtime your schema can still contain:

  • Fields that don’t match the actual TypeScript types.
  • Missing or mismatched resolvers.
  • Incorrect arguments, nullability, or return types.
  • Schema definitions that drift from your resolvers over time.

Existing GraphQL libraries (like type-graphql, nexus) improve the developer experience, but they usually rely on runtime validation or code generation to get some type safety. This often means:

  • You only notice mismatches when you run the app or tests.
  • You may need an extra build step for generating types from SDL.
  • You can accidentally deploy an invalid schema without knowing.

gql-typed solves this by pushing schema validation into the TypeScript type system itself:

  • Type errors at compile time if your schema is invalid.
  • No separate code generation step.
  • The schema itself is a typed object, ensuring resolvers match field definitions.
  • Works incrementally across multiple files, without having to declare everything in one place.
  • Produces plain graphql types at runtime, so you can integrate with any existing GraphQL server.

In short: If your TypeScript compiles, your GraphQL schema is valid.

Usage Example

// Config.ts
export interface Config { // global config for your schema
  context: Context;
  // ... and with optional configurations, like scalarMap, etc.
}

// User.ts
export interface User {
  id: string;
  name: string;
  email: string;
}

// GraphQLUser.ts
export const GraphQLUser = objectType<Config, User>()({
  name: "User",
  fields: {
    id: { type: { type: "ID" } },
    name: {
      description: "login name", // optional description
      type: { type: "String" },
    },
  },
  fieldResolvers: {
    email: resolver<string | undefined>()()({ // say email is authorized field
      type: { nullable: true, type: "String" },
      resolve(user, _args, context, _info) { // this will be passed to graphql
        return context.diContainer.resolve(UserService).getUserEmail(user);
      },
    }),
    postsConnection, // field resolvers can be defined across multiple files
  },
});

// fieldResolvers/Query/userById.ts
export const userById = resolver<User | null, Record<"id", string>>()<
  Config, // in across multiple files, additional generic arguments are required
  {} // type of the parent(`Query`) object (`{}` in this example)
>()({
  type: { nullable: true, type: "User" },
  args: {
    id: { description: "user id", type: { type: "ID" } },
  },
  resolve(_parent, args, context, _info) {
    return context.diContainer.resolve(UserService).getUserById(args.id);
  },
  deprecationReason: "use user instead",
});

// GraphQLQuery.ts
export const GraphQLQuery = objectType<Config, undefined>()({
  name: "Query",
  fieldResolvers: { userById, ...andOtherFieldsInQuery },
});

// schema.ts
export const schema = create<Config>()
  .register(GraphQLQuery, GraphQLUser, ...otherTypes)
  .build({
    Query: {}, // as `{}` is used to represent `Query` object type
    Mutation: {},
  }).schema; // you can chain .register(), or print the schema to a file as well
// type of `schema` will be error message if your schema has validation errors
(<T>(_: Exclude<T, string>) => {})<typeof schema>(schema); // type error if so

Why fn()()(input)?

In TypeScript, you can’t partially infer and partially provide generics in a single call in a clean way. The currying-like syntax:

objectType<Config, User>()({ ... })

allows you to:

  • Pass some generics explicitly.
  • Let the rest be inferred from the input object.
  • Avoid declaring the object separately with as const just to get proper inference.

Without this, you’d need to do:

const def = { ... } as const;
objectType<Config, User, typeof def>(def);

which is verbose and less ergonomic.

If you’re a pure JavaScript user, you can just use the graphql package directly—gql-typed is essentially a type-safe wrapper with compile-time validation.

Features

  • Full compile-time schema validation — no runtime mismatch surprises.
  • Type-safe resolvers — resolver args, parent, and return type are all checked.
  • Multi-file schema definition — works even if field resolvers are split across files.
  • Integrates with existing GraphQL servers — returns standard graphql package objects.
  • No code generation — no extra build step required.
  • Clear, early feedback — if your schema is invalid, TypeScript tells you before running the app.