colinhacks / zod

TypeScript-first schema validation with static type inference
https://zod.dev
MIT License
34.11k stars 1.2k forks source link

[Feature request] Marking a field as deprecated #2622

Open chrskerr opened 1 year ago

chrskerr commented 1 year ago

Use case


I am creating an API using Zod and TRPC, and I can't guarantee that all of the clients will upgrade immediately upon deploy (e.g. long opened tabs).

I would like to deprecate fields out of the TRCP input or output schema without forcing an immediate client refresh; and I didn't spot an approach to doing this in the docs.

If I have missed any easier approach, please let me know :)

Proposal

A deprecated method which removes the key from the input, or output, types based on the setting (naming just a first-thought, not a suggestion).

Why not just temporarily use optional

In both situations, deprecating for a situation-appropriate amount of time helps to avoid API mismatch.

Examples

export const appRouter = t.router({
  hello: publicProcedure
    .input(
      z.object({
        // consumers of this API route will not see `name` in the input types
        // but it is still available here to be responded to for old consumers
        name: z.string().deprecated('input'),
      }),
    )
    .query((opts) => {
      const name = opts.input.name;
      if (name) { /* do the old version */ }
      else { /* do the new version */ } 
      return {
        greeting: "Hello",
      };
    }),
});
export const appRouter = t.router({
  // this method is being deprecated, so new consumers will see `{}` as the output type
  // it will still work for older consumers, allowing time for all clients to update to the latest build
  // this specific situation may be better managed at a TRPC level as well
  hello: publicProcedure
    .input(
      z.object({
        name: z.string().deprecated('input'),
      }),
    )
    .output(
      z.object({
        greeting: z.string().deprecated('output'),
      }),
    )
    .query((opts) => {
      const name = opts.input.name;
      return {
        greeting: "Hello",
      };
    }),
});
okikio commented 8 months ago

How's this comming along?

jthrilly commented 3 months ago

I'd settle for even just a type annotation as a starting point. Would you accept a PR?