Write-Type-Provider

How to write your own type provider

Things to keep in mind when implementing a custom type provider:

Type Contravariance

Whereas exhaustive type narrowing checks normally rely on never to represent an unreachable state, reduction in type provider interfaces should only be done up to unknown.

The reasoning is that certain methods of FastifyInstance are contravariant on TypeProvider, which can lead to TypeScript surfacing assignability issues unless the custom type provider interface is substitutable with FastifyTypeProviderDefault.

For example, FastifyTypeProviderDefault will not be assignable to the following:

  1. export interface NotSubstitutableTypeProvider extends FastifyTypeProvider {
  2. // bad, nothing is assignable to `never` (except for itself)
  3. validator: this['schema'] extends /** custom check here**/ ? /** narrowed type here **/ : never;
  4. serializer: this['schema'] extends /** custom check here**/ ? /** narrowed type here **/ : never;
  5. }

Unless changed to:

  1. export interface SubstitutableTypeProvider extends FastifyTypeProvider {
  2. // good, anything can be assigned to `unknown`
  3. validator: this['schema'] extends /** custom check here**/ ? /** narrowed type here **/ : unknown;
  4. serializer: this['schema'] extends /** custom check here**/ ? /** narrowed type here **/ : unknown;
  5. }