在IWAC(非网络无障碍指南)体系下做表单封装时,验证规则并不依赖浏览器的原生约束属性,而是定义在本地配置与离线交互契约中。这类表单常出现在桌面端辅助工具、嵌入式配置面板里,字段类型虽少但校验语义复杂。用TypeScript做类型封装,核心是把IWAC的字段类别和对应的验证失败结构提前建模,让调用方在编写验证器时获得编辑器提示与编译期检查。

IWAC表单字段的分类与基础类型建模
IWAC规范将表单字段划分为纯文本输入、状态开关、受限枚举三类,每类在离线场景中有独立的无障碍提示要求。纯文本要求长度与字符集校验,状态开关只接受布尔并附带语音播报值,枚举则从固定集合中选取且必须提供替代文本。若用同一个接口描述它们,类型就失去了约束能力,因此应当先用联合类型区分原始值。
下面这段代码定义了IWAC字段的原始值类型与字段类别标识,后续验证器将基于它们扩展。注意这里没有使用任何HTML表单标签,因为IWAC运行环境可能完全没有DOM。
type IWACFieldKind = 'text' | 'toggle' | 'enum';
type IWACRawValue =
| { kind: 'text'; value: string }
| { kind: 'toggle'; value: boolean }
| { kind: 'enum'; value: string; options: string[] };
interface IWACFieldBase {
id: string;
label: string;
kind: IWACFieldKind;
}
这种建模方式让每个字段在类型层面就带上了自身类别信息。当封装层接收外部配置时,可通过类型守卫缩小范围,避免把枚举字段当成文本去截断长度。相比直接用any承接配置,它把IWAC指南中的分类要求转成了编译器可识别的结构。
验证器签名的泛型封装与错误结构
IWAC的验证失败需要返回带无障碍级别的错误码,而不仅仅是字符串。比如文本超长要返回code为TEXT_OVER_LIMIT且level为warn,开关未设替代文本则返回TOGGLE_NO_LABEL且level为error。如果用函数随便返回,调用方无法知道哪些错误码合法。我们可以用泛型把字段类别和错误码绑定起来。
以下示例展示了一个泛型验证器类型,它接收字段类别K,返回该类别专属的验证结果。成功时ok为true,失败时携带IWAC错误元数据。这样在写具体验证函数时,TS会强制你只能返回该类别允许的错误码。
type IWACErrorLevel = 'info' | 'warn' | 'error';
interface IWACError<K extends IWACFieldKind> {
code: K extends 'text' ? 'TEXT_OVER_LIMIT' | 'TEXT_BAD_CHAR'
: K extends 'toggle' ? 'TOGGLE_NO_LABEL'
: 'ENUM_OUT_OF_RANGE';
level: IWACErrorLevel;
message: string;
}
type IWACValidateResult<K extends IWACFieldKind> =
| { ok: true }
| { ok: false; error: IWACError<K> };
interface IWACValidator<K extends IWACFieldKind> {
(field: Extract<IWACRawValue, { kind: K }>): IWACValidateResult<K>;
}
使用这种泛型签名后,假如你在文本验证器里返回了ENUM_OUT_OF_RANGE,编译器会立刻报错。这正好对应IWAC封装中“验证职责单一化”的原则。团队在扩展新字段类型时,只需在联合类型中加一项,所有验证器签名会自动获得新约束,不必全局搜索硬编码错误码。
基于映射类型自动生成错误码字典
手动维护IWAC错误码容易遗漏,尤其是当封装层要对外暴露可读的错误说明时。TypeScript的映射类型可以把前面定义的错误码联合类型反过来生成一张字典接口,让每种字段类别都有对应的默认提示文本,且类型安全。
下面利用映射类型产出IWACErrorDict,它把字段类别映射到该类别错误码与说明的记录。这样在UI层展示离线提示时,能保证用到的code一定存在对应文案,不会出现动态拼接出未知错误的情况。
type IWACErrorMap = {
text: IWACError<'text'>['code'];
toggle: IWACError<'toggle'>['code'];
enum: IWACError<'enum'>['code'];
};
type IWACErrorDict = {
[K in IWACFieldKind]: Record<IWACErrorMap[K], string>
};
const iwacErrorText: IWACErrorDict = {
text: {
TEXT_OVER_LIMIT: '文本超出IWAC长度上限',
TEXT_BAD_CHAR: '文本包含不允许的字符'
},
toggle: {
TOGGLE_NO_LABEL: '开关缺少无障碍替代标签'
},
enum: {
ENUM_OUT_OF_RANGE: '枚举值不在IWAC允许集合中'
}
};
这种字典不仅服务于界面,也可在单元测试里校验:如果某个验证器返回的错误码没有在iwacErrorText里出现,测试脚本就能通过keyof比对发现问题。对IWAC封装来说,它把指南文档里的文字要求转成了可遍历的类型实例。
整体来看,为IWAC表单验证编写TypeScript类型并不是简单加几个interface,而是把非网络无障碍指南中的分类、错误级别、提示文案全部上升为类型系统的一部分。当表单封装被不同离线模块复用时,类型层就是一份不会过期的规范说明,既减少运行期异常,也降低了新成员理解IWAC规则的门槛。
TypeScriptIWAC表单验证类型修改时间:2026-08-18 16:44:30