vanilla extract 本身不提供类型安全,需配合 @vanilla-extract/css + typescript 及 createtheme、defineproperties、stylemap 等 api 实现;style 返回 string 无校验,易拼错类名;stylevariants 支持有限枚举态的联合类型约束;defineproperties + stylemap 可精确推导设计 token 键名类型;主题类型安全需 createthemecontract 或手动标注,动态计算会丢失类型。

Vanilla Extract 本身不提供类型安全的 CSS,它只把 CSS 类名编译成字符串——styles.className 是 string,不是类型化的标识符。真正实现类型安全,得靠它配套的 @vanilla-extract/css + TypeScript 的类型推导能力,配合 createTheme、defineProperties 和 styleMap 这些 API 才能落地。
为什么直接用 style 函数写出来的类名不是类型安全的?
style 返回的是 string,TypeScript 不会校验你传给 className 的值是否真实存在,也不会阻止你拼错类名。比如:
const className = style({ color: 'red' });<br>div.className = 'typo-clas-nam'; // ✅ 编译通过,但运行时无效
这种写法失去类型保护,和手写字符串没区别。
真正安全的方式是:用 createTheme 或 defineProperties 定义明确的样式契约,再通过 styleVariants 或 styleMap 生成带联合类型的返回值。
用 styleVariants 给按钮状态加类型约束
适合「有限枚举态」场景,比如 variant 只能是 'primary' | 'secondary',每个态对应一组样式。TypeScript 能推导出返回值类型为 Record。
- 定义时必须显式写出所有键,不能漏或拼错;否则 TS 报错
- 使用时只能传入合法键名:
button.className = variants[props.variant]—— 如果props.variant是string,会报错;必须是'primary' | 'secondary' - 注意:不要在
styleVariants内部用动态 key,比如[key]: {...},TS 无法推导类型
const variants = styleVariants({<br> primary: { backgroundColor: 'blue' },<br> secondary: { backgroundColor: 'gray' }<br>});
用 defineProperties + styleMap 控制设计 Token 类型
当你有一套固定的设计系统(如 spacing、colors、radii),defineProperties 能把它们声明为对象字面量,并让 TypeScript 推导出精确的键名类型;styleMap 则基于这些属性生成可索引的样式映射。
-
defineProperties的参数必须是 const 断言对象,否则 TS 会宽泛推导为string -
styleMap的第一个参数是defineProperties的返回值,第二个参数是样式规则函数,它接收的 key 参数会被限制为该对象的键名 - 错误示例:
padding: tokens.spacing['xl']中如果'xl'拼错,TS 立刻报错
const tokens = defineProperties({<br> spacing: { sm: '4px', md: '8px', lg: '16px' } as const<br>});<br><br>const paddingMap = styleMap(tokens.spacing, (value) => ({ padding: value }));<br>// paddingMap.sm → string,paddingMap.xl → ❌ TS error
主题切换时如何保持类型不丢失?
createTheme 生成的主题对象本身是类型安全的,但它返回的类名仍是 string。要保留类型,得搭配 createThemeContract(v2+)或手动定义 contract 类型。
- 不用
createThemeContract的话,主题里的每个 class 字段都得手动标注类型,比如container: string -
createThemeContract本质是帮你生成一个 interface,让主题对象满足该结构,从而在消费时获得自动补全和校验 - 注意:主题变量不能在 runtime 动态计算,否则类型信息丢失(例如
color: isDark ? 'black' : 'white')
类型安全不是开箱即来,而是靠你把设计决策提前编码进类型定义里——拼写错误、非法值、多余字段,都会在编辑器里立刻暴露。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











