Skip to content

Invalid declarations emitted when using ZodObject from zod as return type of generic function #54560

@mayorandrew

Description

@mayorandrew

Bug Report

🔎 Search Terms

zod, ZodObject, declaration, invalid declaration emit, extends infer T, union distribution, Type 'k' cannot be used to index type 'addQuestionMarks', skipLibCheck, error 2536, generic function return type

🕗 Version & Regression Information

Observed in all versions starting from 4.7. Tested on 4.7.4, 4.8.4, 4.9.5, 5.0.4, 5.1.3, 5.2.0-dev20230607. Works correctly on 4.6.4.

  • This changed between versions 4.6.4 and 4.7.4
  • This is the behavior in every version I tried, and I reviewed the full FAQ

⏯ Playground Link

The playground contains relevant simplified type definitions from zod library in an attempt to produce a minimal reproducible example.

Playground link with relevant code

💻 Code

export const buildSchema = <V extends string>(version: V): 
  objectOutputType<{ version: ZodLiteral<V>; }> => 
    ({}) as any;

Ignore ({}) as any, it is just to avoid writing function implementation.

🙁 Actual behavior

Code gets compiled into the following declaration:

export declare const buildSchema: <V extends string>(version: V) => addQuestionMarks<baseObjectOutputType<{
    version: ZodLiteral<V>;
}>, undefined extends V ? never : "version"> extends infer T ? { [k in keyof T]: addQuestionMarks<baseObjectOutputType<{
    version: ZodLiteral<V>;
}>, undefined extends V ? never : "version">[k]; } : never;

This declaration produces the following type error when copy-pasted back into TS playground:

Type 'k' cannot be used to index type 'addQuestionMarks<baseObjectOutputType<{ version: ZodLiteral<V>; }>, undefined extends V ? never : "version">'.(2536)

🙂 Expected behavior

The generated declaration should be valid.

For example, this would be a valid declaration:

export declare const buildSchema: <V extends string>(version: V) => addQuestionMarks<baseObjectOutputType<{
    version: ZodLiteral<V>;
}>, undefined extends V ? never : "version"> extends infer T ? { [k in keyof T]: T[k]; } : never;

4.6.4 produces declaration without extends infer T which is also valid:

export declare const buildSchema: <V extends string>(version: V) => { [k in keyof addQuestionMarks<baseObjectOutputType<{
    version: ZodLiteral<V>;
}>, undefined extends V ? never : "version">]: addQuestionMarks<baseObjectOutputType<{
    version: ZodLiteral<V>;
}>, undefined extends V ? never : "version">[k]; };

Related issues:

Special thanks to @KaoSDlanor for posting an issue in the zod repo than inspired me to write this one and @pivstone for helping me with the investigation

Metadata

Metadata

Assignees

Labels

BugA bug in TypeScriptFix AvailableA PR has been opened for this issueRescheduledThis issue was previously scheduled to an earlier milestone

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions