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

如何在Yup对象Schema中将字符串联合类型定义为对象键

问题解法

首先明确核心前提:TypeScript 的类型信息会在编译阶段被完全擦除,而 Yup 是运行时校验库,无法直接读取你定义的字符串联合类型做键规则约束,必须先提供运行时可访问的联合类型对应值列表,再配合 Yup 的 API 完成 Schema 定义。


步骤1:定义运行时可用的键列表

不要单独硬编码联合类型,先声明常量数组存储所有合法键值,再通过 TS 语法反向推导联合类型,避免类型定义和运行时值不一致:

const TAG_LIST = ["a", "b", "c"] as const;
type Tag = typeof TAG_LIST[number]; // 推导结果等价于 "a" | "b" | "c"
type Obj = Record<Tag, number>; // 和你之前定义的索引对象类型完全一致

步骤2:补全对象Schema定义

根据你的校验需求选对应写法即可:

场景1:要求对象必须包含所有Tag键,不允许额外键

你写的obj({ [??]: number() })结构里,[??]位置不能直接写TS类型语法,需要通过Object.fromEntries把键列表转成每个键对应number()规则的普通JS对象传入:

import { object, number } from "yup";

const objSchema = object(
  Object.fromEntries(
    TAG_LIST.map((key) => [key, number().required()])
  ) as Record<Tag, ReturnType<typeof number>>
).required().noUnknown();

这个Schema推导出来的TS类型和你定义的Obj完全匹配,运行时会校验a/b/c三个键必须存在且值为数字,链式调用的.noUnknown()会拦截不在Tag列表里的额外键。

场景2:仅要求对象的键属于Tag范围,不强制包含所有键

不需要手动构造键值对象,直接用Yup内置的record方法即可:

import { mixed, number, record } from "yup";

const tagSchema = mixed<Tag>().oneOf(TAG_LIST).required();
const objSchema = record(tagSchema, number().required()).required();

注意:你之前单独写的const tag = mixed<"a" | "b" | "c">().required()缺少运行时值校验,必须加上.oneOf(TAG_LIST)才能在运行时拦截不在联合范围内的非法值,仅靠泛型约束只能在TS编译阶段生效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 11:48:27