ts-rest / ts-rest

RPC-like client, contract, and server implementation for a pure REST API
https://ts-rest.com
MIT License
2.31k stars 108 forks source link

use c.type to write router headers and baseHeaders { readonly [tag]: .... } #602

Closed KenjiGinjo closed 1 month ago

KenjiGinjo commented 4 months ago

Describe the bug

I encountered an issue with using c.type to write router, when I initialize client, ts give me an error about a required 'headers' . I think the issue perhaps in

// dsl.ts 
type UniversalMerge = ...

only when I combined header with baseHeaders can rise this issue

How to reproduce

Expected behavior

  client.posts.getPost({}) // should not throw ts error

Code reproduction

  const contract = c.router(
      {
        posts: {
          getPost: {
            method: 'GET',
            path: '/posts/:id',
            responses: {
              200: c.type<{
                id: number;
              }>(),
            },
            headers: c.type<{
              'x-bar': string;
            }>(),
          },
        },
      } , {
        baseHeaders:c.type<{
          'x-foo': string
        }>(),
      },
    );
    const client = initClient(contract, {
      baseUrl: 'https://api.com',
      baseHeaders: {
        'x-foo': 'foo',
      },
    });

    client.posts.getPost({}) // require a  readonly [tag]: ContractPlayType parameter

// this test failed too.
    type ContractShape = Expect<
      Equal<
        typeof contract,
        {
          posts: {
            getPost: {
              method: 'GET';
              path: '/posts/:id';
              responses: {
                200: ContractPlainType<{
                  id: number;
                }>;
              };
              headers: ContractPlainType<{ 'x-bar': string , 'x-foo': string }>;
            };
          };
        }
      >
    >;

ts-rest version

3.45.2

Gabrola commented 1 month ago

Took too long to get to this for a relatively easy fix. Thank you for reporting!