在跨国项目的无障碍合规工作中,牙买加网络无障碍指南(简称IWAC)对颜色使用提出了比常规WCAG更细化的本地化要求。其中一条核心规则是:任何传递状态的信息都不能仅依赖颜色,且文本与背景的对比度必须满足特定阈值。当我们用TypeScript开发前端组件库时,如果能把这些规则直接编码进类型系统,就可以在写代码的过程中挡住大部分违规用法。

理解IWAC颜色依赖条款与类型建模目标
IWAC指南里关于颜色依赖的描述主要分成两层。第一层是对比度数值约束,例如正文文本与底色之间至少需要4.5比1的亮度差,大号字体放宽到3比1。第二层是语义传递约束,也就是错误、成功等状态除颜色外必须有文字或图标辅助。传统做法是在运行时用函数计算对比度并抛错,但错误发现得太晚,常常已经写完了整个页面。
我们要用TypeScript做的,是把这两层约束变成类型层面的限制。比如定义一个ColorToken类型,它不只是十六进制字符串,而是附带了亮度等级信息的字面量。再定义一个StatusPair泛型,要求传入的前景和背景必须来自通过对比度校验的预设组合。这样开发者在选择颜色时,如果选了不在白名单里的搭配,编译器会直接标红。
这种建模并不追求在类型里实现完整的色彩空间数学运算,而是把IWAC文档中已核准的配色方案固化为联合类型,把禁止单色提示变成接口必填字段。这样既满足了指南要求,又不会让类型系统复杂到无法维护。下面我们看具体的类型代码结构。
封装颜色令牌与对比度约束类型
先来定义基础的颜色令牌。我们假设设计系统只放出有限的几种背景与前景色,并且已经人工核对过它们符合IWAC对比度。用字面量联合可以避免随意传参:
// 已核对符合IWAC对比度阈值的背景色
type IwacBackground = '#FFFFFF' | '#1A1A1A' | '#F2F2F2';
// 已核对符合IWAC对比度阈值的前景文本色
type IwacForeground = '#000000' | '#FFFFFF' | '#333333';
// 仅允许背景与前景来自合规组合
type CompliancePair<B extends IwacBackground, F extends IwacForeground> = {
background: B;
foreground: F;
};
// 预定义合规组合白名单
type ApprovedCombo =
| CompliancePair<'#FFFFFF', '#000000'>
| CompliancePair<'#1A1A1A', '#FFFFFF'>
| CompliancePair<'#F2F2F2', '#333333'>;
上面的代码把IWAC的对比度要求转成了ApprovedCombo联合类型。任何函数如果需要接收颜色对,就声明参数为ApprovedCombo,这样传错组合会在编辑阶段报错。注意我们并没有在类型里算相对亮度,而是把文档结论直接写成联合,这对大多数团队来说已经足够且易读。
接下来处理禁止单色提示的条款。IWAC规定状态色不能单独使用,必须配合文本标签。我们可以用一个泛型接口强制调用方提供非颜色的提示内容:
interface IwacStatusProps<T extends ApprovedCombo> {
colorPair: T;
// 必须提供文字或图标描述,不能只靠颜色
ariaLabel: string;
iconName?: 'check' | 'cross' | 'warn';
}
function renderStatus<T extends ApprovedCombo>(props: IwacStatusProps<T>) {
return props;
}
// 正确使用:带了文字说明
renderStatus({ colorPair: { background: '#1A1A1A', foreground: '#FFFFFF' }, ariaLabel: '提交成功' });
// 若漏掉 ariaLabel 则编译失败,满足IWAC非颜色依赖要求
通过把ariaLabel设为必填,类型系统帮我们落实了指南里禁止单色提示的精神。如果有人想只改背景色来表达错误状态,要么凑不齐ApprovedCombo,要么通不过ariaLabel检查,两种都会被拦下。
在组件库与构建流程中落地封装
把上述类型放进共享包后,前端组件应当统一引用,而不是各自定义颜色属性。例如在按钮组件里,我们不再接受任意string类型的bg和fg,而是要求传入ApprovedCombo成员:
import type { ApprovedCombo } from '@design/iwac-types';
interface ButtonProps {
combo: ApprovedCombo;
children: string;
}
function Button({ combo, children }: ButtonProps) {
return {
style: { background: combo.background, color: combo.foreground },
text: children
};
}
这样的组件在接入设计系统的主题文件时,主题文件只需导出合规组合对象,业务开发便无法擅自引入高危颜色。同时建议在CI中加入tsc --noEmit严格校验,保证类型约束不会被任何跳过编译的步骤绕过。
另一个常见场景是动态换肤。若运营后台允许用户输入十六进制色值,则输入层必须做运行时校验,通过后再映射到最近的ApprovedCombo,而不能直接把用户输入塞给组件。类型层负责静态代码安全,运行时负责动态数据卫生,两者配合才能完整覆盖IWAC要求。经过这样的封装,团队在牙买加地区上线时就不需要反复人工审色板,合规成本显著下降。
TypeScriptIWACcolor_dependency_type修改时间:2026-08-14 03:51:28