Type inference issue with extending/narrowing enum types in generic schemas
I'm encountering a TypeScript error when trying to extend/narrow an enum type in a generic schema context. While TypeScript normally allows narrowing of enum types, this doesn't seem to work properly with Zod's type system.
import { z } from 'zod';
// Base schema with broader enum
const baseSchema = z.object({
gender: z.enum(["Rüde", "Hündin", "männlich", "weiblich"]).nullable(),
// ... other fields
});
// Trying to create a more specific schema with narrower enum
const dogSchema = z.object({
gender: z.enum(["Rüde", "Hündin"]).nullable(),
// ... other fields
});
// Generic interface that should accept both schemas
interface MyInterface<T extends typeof baseSchema> {
schema: T;
// ... other properties
}
// This fails with type error even though dogSchema's enum is a subset of baseSchema's enum
const implementation: MyInterface<typeof dogSchema> = {
schema: dogSchema
};
the type error probobly happens since zod is saying that
Type 'ZodEnum<["Rüde", "Hündin"]>' is not assignable to type 'ZodEnum<["Rüde", "Hündin", "männlich", "weiblich"]>
Expected Behavior
Since the enum in dogSchema is a subset of the enum in baseSchema, and TypeScript normally allows this kind of type narrowing, the implementation should type-check successfully.
Actual Behavior
TypeScript produces an error indicating that the narrower enum type is not assignable to the broader enum type when used in this generic context with Zod schemas.
Possible Solutions
One potential solution might be to add a utility type or method to Zod that explicitly handles enum narrowing in generic contexts, similar to how TypeScript handles normal enum type narrowing.
Hi, zod does not actually know that the values are the same, does it?
Have you tried with .extend or .merge?
Hi, @AnzeKop. I'm Dosu, and I'm helping the Zod team manage their backlog. I'm marking this issue as stale.
Issue Summary:
- You reported a TypeScript error when narrowing an enum type within a generic schema using Zod.
- The issue arises because Zod's type system does not recognize the narrower enum as a subset of the broader enum.
- @m10rten suggested using
.extendor.mergeas potential solutions and questioned if Zod recognizes the values as the same. - You are seeking a utility type or method in Zod to handle enum narrowing in generic contexts.
Next Steps:
- Please let me know if this issue is still relevant to the latest version of the Zod repository. If so, you can keep the discussion open by commenting on the issue.
- Otherwise, the issue will be automatically closed in 7 days.
Thank you for your understanding and contribution!
You're right—Zod treats each z.enum as a distinct schema, even if their values overlap or one is a subset of the other. It doesn't infer compatibility between enums the way TypeScript does for unions or enums, so you get a type error in generic contexts like this.
The .extend and .merge methods are designed for object schema composition: they add or overwrite fields, but they don't perform deep compatibility checks or support enum narrowing. If you use .extend to replace an enum field, it simply swaps the schema for that key, not narrows it or checks for subset compatibility (docs, changelog).
If you want to create a narrowed enum based on a broader one, you can use the extract or exclude methods on ZodEnum to manually create a subset:
const baseEnum = z.enum(["Rüde", "Hündin", "männlich", "weiblich"]);
const dogEnum = baseEnum.extract(["Rüde", "Hündin"]);
But there's no built-in mechanism for automatic enum narrowing in generics—manual intervention is required (source). For generic schema patterns, you may need to use explicit type annotations or type assertions to help TypeScript along (relevant discussion).
If you need more targeted help, feel free to share a minimal reproduction. If this answers your question, please close the issue!
To reply, just mention @dosu.
How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other
@dosu this is still an issue. subsets don't fix the type missmatch when defining an interface thats meant to be a base
@colinhacks, the user AnzeKop has indicated that this issue is still relevant and needs attention. Could you please take a look?
@colinhacks, the user @AnzeKop has indicated that this issue is still relevant despite being marked stale and closed. Could you please take a look and assist them?
You're right—this is still an open issue. Zod treats each z.enum as a distinct schema, so TypeScript doesn't see a narrower enum as assignable to a broader one, even if the values are a subset. This is a TypeScript type inference limitation, not a Zod bug, and Zod 4 does not introduce automatic enum narrowing in generics. The community has discussed this in detail (#4735, #4698, #4580, #4877).
Recommended workarounds are: define concrete schemas up front instead of using generic factories, use type assertions, use manual type guards, or provide explicit return types for schema-producing functions. In Zod 4, use ZodType<T> or ZodTypeAny as your generic constraint (not ZodSchema), and prefer .extend for schema extension, though this doesn't solve enum subset compatibility.
If you have a minimal reproduction or a specific outcome you're aiming for, feel free to share it for more targeted help. If this answers your question, please close the issue.
To reply, just mention @dosu.
How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other
Unfortunately Zod isn't perfect in this regard—just because the inferred type of schema A extends the inferred type of schema B doesn't mean A will be assignable to B. Enums present a particular challenge because Zod needs to track an "enum-like" type as a generic. Adding additional fields to the enum-like generic refines the generic but loosens the inferred type. There's no solution I've found for this.
Consider this approach instead:
// Generic interface that should accept both schemas
interface MyInterface<T extends z.ZodType<z.infer<typeof baseSchema>>> {
schema: T;
// ... other properties
}