Fastify: Support for Auto Type Inference (similar to TRPC)

Hello!

Why are we providing types using an object, rather than type annotation which is the common way?

Type annotations do not provide type safety at runtime (remembering annotations are erased on compilation). Libraries such as Zod, IO-TS, Runtypes, etc, enable runtime type safety....with the caveat being you need to represent your type in JavaScript in some capacity for runtime assertions to be possible. Many of these libraries are becoming very popular today, particularly Zod.

Looks like a very non-idiomatic way, in TypeScript, to inject types

The Type Provider system in Fastify can be loosely viewed as a type plugin system that allows a multitude of these runtime validation libraries (such as Zod) to be integrated into Fastify route handlers (allowing them to leverage the libraries inference). This with the goal of allowing users to bind in their library of choice to get all the benefits of runtime type safety, as well as get auto type inference on routes.

So, rather than Fastify implementing type definitions internally to integrate all possible runtime type libraries (of which there are literally dozens), the Type Provider system instead allows one to integrate the runtime library "externally". The following binds in a variety of different libraries.

Zod

import z from 'zod'

export interface ZodTypeProvider extends FastifyTypeProvider {
  output: this['input'] extends z.ZodTypeAny ? z.infer<this['input']> : unknown;
}

TypeBox

import { TSchema, Static } from '@sinclair/typebox'

export interface TypeBoxTypeProvider extends FastifyTypeProvider {
  output: this['input'] extends TSchema ? Static<this['input']> : unknown
}

Yup

import yup, { ISchema, InferType } from 'yup'

export interface YupTypeProvider extends FastifyTypeProvider {
  output: this['input'] extends ISchema<any, any, any, any> ? InferType<this['input']> : unknown
}

JSON Schema To TS

import { JSONSchema7, FromSchema, FromSchemaOptions, FromSchemaDefaultOptions } from 'json-schema-to-ts'

export interface JsonSchemaToTsProvider<Options extends FromSchemaOptions = FromSchemaDefaultOptions> extends FastifyTypeProvider {
  output: this['input'] extends JSONSchema7 ? FromSchema<this['input'], Options> : unknown;
}

If you copy and paste the original code snippet (above) into the TypeScript Playground, you should get a sense of the benefits.

Hope that helps!

/r/typescript Thread Parent