#5686·zod

Zod incorrectly points to CommonJS declaration when used with ESM

Author: patrickshipeCreated Feb 4, 2026Updated Sep 16, 2026

In Zod's package.json exports setting, the main entry point for both CJS and ESM resolves to the same index.d.cts declarations file. In most cases, this does not cause issues. However, there is an issue that arises when declaration files are compiled for an ESM project with module nodenext. If I use this output in the frontend with module ESNext, the declaration file will not be legible and all inferred types will be any. This is because based on the cts extension, TypeScript assumes Zod to be a CommonJS module and treats it differently based on Node mdoule interop rules. The package.json exports field should be modified to point to the correct declarations file (index.d.ts) for the import condition.

More details:

With this TypeScript input (package.json type is set to module, tsconfig is set up with module nodenext):

import z from 'zod';

export const personSchema = z.object({
  name: z.string(),
});

export type Person = z.infer<typeof personSchema>;

We get this output:

import z from 'zod';
export declare const personSchema: z.ZodObject<{
    name: z.ZodString;
}, z.z.core.$strip>;
export type Person = z.infer<typeof personSchema>;

Note the z.z path that will fail when this library is used.

Running tsx --traceResolution shows us: ======== Module name 'zod' was successfully resolved to '.../node_modules/zod/index.d.cts' with Package ID 'zod/[email protected]'. ========

if I correct the export condition for . to read (note the different types for import) to:

    ".": {
      "@zod/source": "./src/index.ts",
      "import": {
        "default": "./index.js",
        "types": "./index.d.ts"
      },
      "require": {
        "default": "./index.cjs",
        "types": "./index.d.cts"
      }
    },

We get a correct export:

import z from 'zod';
export declare const personSchema: z.ZodObject<{
    name: z.ZodString;
}, z.core.$strip>;
export type Person = z.infer<typeof personSchema>;

And we get correct module resolution: ======== Module name 'zod' was successfully resolved to 'node_modules/zod/index.d.ts' with Package ID 'zod/[email protected]'. ========