Skip to content

Types not resolving correctly after 2.9.2 #183

@hamanuha

Description

@hamanuha

Hi,

first of all I want to say thank you for this great library!

I use it to share typed api routes between backend and frontend.
Basically I define a contract using json schemas. This is then used for the validation and for the types on the backend and for creating the queries for the frontend.

Unfortunately upgrading to 2.12.0 or 3.0.0 breaks my code.
I heavily simplified the example below to show the issue. Some types seem to be not needed but this is due to the simplification.

If I define the schema externally for initContract then this works with the newer versions as well.
But my inline schema for the params property only works with version 2.9.2.

Any idea what causes this behaviour?
I would like to continue using inline schema definitions.

Types with 2.9.2
types-2-9-2

Types with 2.12.0
types-2-12-0

Simplified example

import type { FromSchema, JSONSchema } from 'json-schema-to-ts'

// Simplified version
type ContractRoute = {
  params: JSONSchema
  query: JSONSchema
}

type Contract = {
  [key: string]: ContractRoute
}

type ProcessContract<T extends Contract> = {
  [K in keyof T]: T[K]
}

const initContract = <TRouter extends Contract>(routes: ProcessContract<TRouter>): TRouter => routes

type ContractRouteImplementation<T extends ContractRoute> = () => {
  handler: (request: { Params: FromSchema<T['params']>; Query: FromSchema<T['query']> }) => void
}

type ServerObj<T extends Contract> = {
  [TKey in keyof T]: ContractRouteImplementation<T[TKey]>
}

type InitialisedServer<T extends Contract> = {
  contract: T
  routes: ServerObj<T>
}

const initServer = <T extends Contract>(contract: T, routes: ServerObj<T>): InitialisedServer<T> => ({
  contract,
  routes,
})

// Example
const externSchema = {
  type: 'object',
  properties: {
    str: { type: 'string' },
  },
  required: ['str'],
  additionalProperties: false,
} as const

const contract = initContract({
  demo: {
    params: {
      type: 'object',
      properties: {
        str: { type: 'string' },
      },
      required: ['str'],
      additionalProperties: false,
    } as const,
    query: externSchema,
  },
})

initServer(contract, {
  demo: () => ({
    handler: async (request) => {},
  }),
})

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions