`Type 'k' cannot be used to index type` error in compiled TypeScript
This code, when put through tsc, contains a type error in the generated declaration file.
const schemaFactory = <ObjectType>(objectTypeSchema: ZodType<ObjectType>) =>
z.object({node: objectTypeSchema});
Repro link: https://github.com/brandongit2/zod-bug-repro
I've committed the output of tsc at dist/index.d.ts. Opening that declaration file in my editor, I see the following TypeScript error:
I think it's to do with the type parameter. For example, this compiles fine:
const schemaFactory = (objectTypeSchema: ZodType<any>) =>
z.object({node: objectTypeSchema});
The erroring code in the .d.ts file takes this form, which I can confirm does cause an error:
type A = {
foo: string;
bar: string;
} extends infer T ? {[k in keyof T]: { // <-- Type 'k' cannot be used to index type '{ foo: string; bar: string; }'.
foo: string;
bar: string;
}[k]} : never;
But extracting the object type to its own type seems to fix it:
type Obj = {
foo: string;
bar: string;
}
type A = Obj extends infer T ? {[k in keyof T]: Obj[k]} : never;
I hope that's relevant.
There was a similar-looking error reported in https://github.com/colinhacks/zod/issues/110, but that doesn't seem to be relevant.
Hitting same issue. Any ideas on fixes or workarounds?
@agorischek I don't like having to do it, but I had to set "skipLibCheck": true in my tsconfig.json.
@agorischek I don't like having to do it, but I had to set
"skipLibCheck": truein mytsconfig.json.
Got it, thanks! I added @ts-nocheck to ignore the built file, but hoping there's something that can be changed inside Zod. Also seems like there's potentially a TypeScript bug here too? Thank you for reporting!
Some more investigation: it seems to do with the objectOutputType and objectInputType utility types used internally by Zod.
(I also figured out a workaround; see bottom)
All I know is:
-
z.object()has this function signature:<T extends ZodRawShape>(shape: T, params?: RawCreateParams) => ZodObject< T, "strip", ZodTypeAny, objectOutputType<T, ZodTypeAny, "strip">, objectInputType<T, ZodTypeAny, "strip"> >; -
objectOutputTypelooks like this: (objectInputTypeis really similar)type objectOutputType< Shape extends ZodRawShape, Catchall extends ZodTypeAny, UnknownKeys extends UnknownKeysParam = UnknownKeysParam > = objectUtil.flatten<objectUtil.addQuestionMarks<baseObjectOutputType<Shape>>> & CatchallOutput<Catchall> & PassthroughType<UnknownKeys>; -
When my type param (from the original issue,
ObjectType) ends up inz.object(), what should beobjectOutputType<ObjectType, ZodTypeAny, "strip">gets transformed into this at compile time:z.objectUtil.addQuestionMarks< z.baseObjectOutputType< {node: z.ZodType<ObjectType, z.ZodTypeDef, ObjectType>} >, any > extends infer T ? { [k in keyof T]: z.objectUtil.addQuestionMarks< z.baseObjectOutputType< {node: z.ZodType<ObjectType, z.ZodTypeDef, ObjectType>} >, any >[k]; } : never
And it's that extends infer T bit I mentioned in my original issue that gives the error. I have no idea where it's coming from; it doesn't seem to come from Zod's source code, but rather it seems to have been introduced by TypeScript itself.
What's suspicious is that objectUtil.flatten and the type intersections (& CatchallOutput<Catchall> & PassthroughType<UnknownKeys>) disappeared.
Workaround
Just override the return of z.object() with the same thing, but removing the objectUtil.flatten and type intersection parts. For this particular schema, they're not useful.
https://github.com/brandongit2/zod-bug-repro/blob/workaround/index.ts:
export const schemaFactory = <ObjectType>(objectTypeSchema: ZodType<ObjectType>) => {
const schemaShape = {node: objectTypeSchema};
return z.object(schemaShape) as ZodObject<
typeof schemaShape,
'strip',
ZodTypeAny,
baseObjectOutputType<typeof schemaShape>,
baseObjectInputType<typeof schemaShape>
>;
};
I just hit the same issue with a schema factory as well:
export const DocContextSchema = <T extends z.ZodTypeAny>(dataSchema: T) =>
z
.object({
collection: z.string(),
key: z.string(),
data: dataSchema
})
.strict();
Thanks for the workaround @brandongit2, it did the job for me as well (PR), just had to tweak strip for strict.
Glad the workaround helped! This TypeScript error comes up with generic schema factories in Zod because of how TypeScript infers types from Zod's internal utility types—especially when emitting .d.ts files. It's a mix of TypeScript's generics limitations and the way Zod v3 structures its object types. The most robust solutions are to provide explicit return type annotations for your schema factories or to upgrade to Zod 4, which reworks generics and type inference for these cases and removes the need for ZodTypeAny altogether (Zod 4 changelog, related issue). Your approach of tweaking the return type and using 'strict' is totally valid. If this resolves your question, feel free to close the issue!
To reply, just mention @dosu.
How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other