You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为含动态字段的路径创建TypeScript类型守卫

Zod联合类型Schema的类型守卫实现方案

场景说明

现有Schema类型的schema字段支持两种取值格式:

  • 直接存储ZodTypeAny类型的Zod schema实例
  • 存储以Key联合类型值为键、对应Zod schema实例为值的键值对映射对象
    直接对该字段做下标取值时,TypeScript会报类型错误,需要通过类型守卫完成类型收窄。

完整实现代码

import * as z from 'zod';
import type { ZodTypeAny } from 'zod'

type Key = 'test' | 'test2' | 'test3'

// 拆分两种schema类型,提升可读性
type SingleSchema = ZodTypeAny;
type SchemaMap = Partial<Record<Key, ZodTypeAny>>;

type Schema = {
  schema?: SingleSchema | SchemaMap
}

/**
 * 类型守卫:判断入参是否为单个Zod schema实例
 * 判断依据:Zod实例自带safeParse/parse等专属方法,普通映射对象不存在该属性
 */
const isSingleSchema = (value: unknown): value is SingleSchema => {
  return typeof value === 'object'
    && value !== null
    && 'safeParse' in value
    && typeof (value as SingleSchema).safeParse === 'function';
};

const userSchema = z.object({
  name: z.string(),
  email: z.string(),
});

const getSchema = (key: Key, path: Schema): ZodTypeAny | undefined => {
  const schemaConfig = path.schema;
  if (!schemaConfig) return undefined;
  // 收窄为单个schema场景,直接返回
  if (isSingleSchema(schemaConfig)) {
    return schemaConfig;
  }
  // 剩余分支TS自动收窄为SchemaMap类型,按键取值即可
  return schemaConfig[key];
}

// 测试调用,类型校验完全正常
getSchema('test', { schema: {'test':  userSchema} });
getSchema('test', { schema: userSchema });

注意事项

不要通过「对象是否包含Key类型的键」做类型判断:SchemaMap的所有键都是可选属性,空对象{}也是合法的SchemaMap值,这种判断逻辑会出现误判。基于Zod实例内置特征的判断方式稳定性最高。

内容的提问来源于stack exchange,提问作者DevOverflow

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 04:36:23