Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generic schema builder compiles into invalid type definitions #2260

Open
KaoSDlanor opened this issue Mar 28, 2023 · 3 comments
Open

Generic schema builder compiles into invalid type definitions #2260

KaoSDlanor opened this issue Mar 28, 2023 · 3 comments
Labels
stale No activity in last 60 days

Comments

@KaoSDlanor
Copy link

If you define a function which accepts a generic type parameter and returns a Zod object schema containing a string literal based on that type parameter then the code looks fine and typescript will compile it

The declaration file emitted is invalid though and cannot be imported into another project

Minimal reproduction:

./src/index.ts

import { z } from 'zod';

export const schemaBuilder = <V extends string>(version: V) => {
  return z.object({
    version: z.literal<V>(version),
  });
};

When compiled will emit the following declaration file
./dist/index.d.ts

import { z } from 'zod';
export declare const schemaBuilder: <V extends string>(version: V) => z.ZodObject<{
    version: z.ZodLiteral<V>;
}, "strip", z.ZodTypeAny, z.objectUtil.addQuestionMarks<z.baseObjectOutputType<{
    version: z.ZodLiteral<V>;
}>, undefined extends V ? never : "version"> extends infer T ? { [k_1 in keyof T]: z.objectUtil.addQuestionMarks<z.baseObjectOutputType<{
    version: z.ZodLiteral<V>;
}>, undefined extends V ? never : "version">[k_1]; } : never, z.baseObjectInputType<{
    version: z.ZodLiteral<V>;
}> extends infer T_1 ? { [k_2 in keyof T_1]: z.baseObjectInputType<{
    version: z.ZodLiteral<V>;
}>[k_2]; } : never>;

When imported this throws the errors:

./dist/index.d.ts:6:84 - error TS2536: Type 'k_1' cannot be used to index type 'addQuestionMarks<baseObjectOutputType<{ version: ZodLiteral<V>; }>, undefined extends V ? never : "version">'

./dist/index.d.ts:10:46 - error TS2536: Type 'k_2' cannot be used to index type 'baseObjectInputType<{ version: ZodLiteral<V>; }>'.

I can't seem to find where the extends infer T is coming from on line 6 anywhere in the Zod code. Same goes for the extends infer T_1 on line 10

Relevant configuration:

  • Zod version: 3.21.4
  • Typescript version: 4.9.5 (also tested on v5)
  • tsconfig.json:
{
 "compilerOptions": {
   "lib": [ "es2015" ],
   "sourceMap": true,
   "target": "es5",
   "outDir": "./dist",
   "baseUrl": "./src",
   "declaration": true,
   "moduleResolution": "node",
   "esModuleInterop": true,
   "strict": true
 },
 "include": [
   "src/**/*.ts"
 ],
 "exclude": [
   "node_modules"
 ]
}
  • Build pipeline: Just running tsc

Additional information

If the generic function directly returns a Zod literal schema based on the passed generic then everything seems to work fine. Only putting that literal into an object seems to break the definition

@mayorandrew
Copy link

mayorandrew commented Jun 7, 2023

This is also an issue for us (cc @pivstone). extends infer T seems to be added by the TS compiler since version 4.7 and is breaking ZodObject types.

We found a couple of seemingly relevant issues in the TS and zod repos:

The first two are fixed and released in TS 4.8, but we still experience the same issue in TS >= 4.8.

The intention of infer T seems to be about stricter union handling, as noted by TS maintainer @weswigham here.

I believe this is more of a TS issue. I have created a minimal reproduction example in TS Playground and submitted an issue in the TS repo: microsoft/TypeScript#54560

The culprit appears to be the combination of generic object-type transformation helpers. If I remove any one of them, then the compiled declaration does not have the extends infer T stuff and it works correctly.

@stale
Copy link

stale bot commented Sep 7, 2023

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale No activity in last 60 days label Sep 7, 2023
@Daniel-Olivier
Copy link

@mayorandrew You can work around the issue by setting the skipLibCheck compiler option in the project you want to use the schema in

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
stale No activity in last 60 days
Projects
None yet
Development

No branches or pull requests

3 participants