Skip to content

Commit f90957f

Browse files
committed
fix(api): widen asString return type to string
asString returned the ZodEnum unchanged, so z.infer leaked the literal union. Consumers bind their own zod for the @anatine/zod-openapi and @ts-rest/core peers; under zod 4 the union breaks assignments from plain string data (e.g. certification, gender, known_for_department). Annotate the return as z.ZodString so the inferred output stays string regardless of the consumer's zod. Runtime still validates enum membership and the OpenAPI schema stays type: string.
1 parent d2452da commit f90957f

1 file changed

Lines changed: 8 additions & 3 deletions

File tree

  • projects/api/src/contracts/_internal

projects/api/src/contracts/_internal/z.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,14 @@ export function int64(schema: z.ZodNumber) {
3333
*/
3434
export function asString<T extends z.ZodEnum<[string, ...string[]]>>(
3535
schema: T,
36-
) {
37-
// Use type assertion to access the openapi method
38-
return (schema as T & { openapi: (meta: unknown) => T })
36+
): z.ZodString {
37+
// The inferred output must stay `string`, not the literal union: consumers
38+
// bind their own zod for the @anatine/zod-openapi peer, and under zod 4 the
39+
// enum would otherwise leak as a literal union and break assignments from
40+
// plain string data. Runtime keeps validating enum membership.
41+
return (schema as unknown as z.ZodString & {
42+
openapi: (meta: unknown) => z.ZodString;
43+
})
3944
.openapi({
4045
type: 'string',
4146
enum: undefined,

0 commit comments

Comments
 (0)