zod#ZodDiscriminatedUnionDef TypeScript Examples

The following examples show how to use zod#ZodDiscriminatedUnionDef. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: union.ts    From zod-to-json-schema with ISC License 6 votes vote down vote up
asAnyOf = (
  def: ZodUnionDef | ZodDiscriminatedUnionDef<any, any, any>,
  refs: References
): JsonSchema7PrimitiveUnionType | JsonSchema7AnyOfType | undefined => {
  const anyOf = (
    def.options instanceof Map ? Array.from(def.options.values()) : def.options
  )
    .map((x, i) => parseDef(x._def, refs.addToPath("anyOf", i.toString())))
    .filter((x): x is JsonSchema7Type => !!x);

  return anyOf.length ? { anyOf } : undefined;
}
Example #2
Source File: union.ts    From zod-to-json-schema with ISC License 5 votes vote down vote up
export function parseUnionDef(
  def: ZodUnionDef | ZodDiscriminatedUnionDef<any, any, any>,
  refs: References
): JsonSchema7PrimitiveUnionType | JsonSchema7AnyOfType | undefined {
  if (refs.target === "openApi3") return asAnyOf(def, refs);

  const options: readonly ZodTypeAny[] =
    def.options instanceof Map ? Array.from(def.options.values()) : def.options;

  // This blocks tries to look ahead a bit to produce nicer looking schemas with type array instead of anyOf.
  if (
    options.every(
      (x) =>
        x._def.typeName in primitiveMappings &&
        (!x._def.checks || !x._def.checks.length)
    )
  ) {
    // all types in union are primitive and lack checks, so might as well squash into {type: [...]}

    const types = options.reduce((types: JsonSchema7Primitive[], x) => {
      const type = primitiveMappings[x._def.typeName as ZodPrimitive]; //Can be safely casted due to row 43
      return type && !types.includes(type) ? [...types, type] : types;
    }, []);

    return {
      type: types.length > 1 ? types : types[0],
    };
  } else if (options.every((x) => x._def.typeName === "ZodLiteral")) {
    // all options literals

    const types = options.reduce(
      (acc: JsonSchema7Primitive[], x: { _def: ZodLiteralDef }) => {
        const type = typeof x._def.value;
        switch (type) {
          case "string":
          case "number":
          case "boolean":
            return [...acc, type];
          case "bigint":
            return [...acc, "integer" as const];
          case "object":
            if (x._def.value === null) return [...acc, "null" as const];
          case "symbol":
          case "undefined":
          case "function":
          default:
            return acc;
        }
      },
      []
    );

    if (types.length === options.length) {
      // all the literals are primitive, as far as null can be considered primitive

      const uniqueTypes = types.filter((x, i, a) => a.indexOf(x) === i);
      return {
        type: uniqueTypes.length > 1 ? uniqueTypes : uniqueTypes[0],
        enum: options.reduce((acc, x) => {
          return acc.includes(x._def.value) ? acc : [...acc, x._def.value];
        }, [] as (string | number | bigint | boolean | null)[]),
      };
    }
  } else if (options.every((x) => x._def.typeName === "ZodEnum")) {
    return {
      type: "string",
      enum: options.reduce(
        (acc: string[], x) => [
          ...acc,
          ...x._def.values.filter((x: string) => !acc.includes(x)),
        ],
        []
      ),
    };
  }

  return asAnyOf(def, refs);
}