TypeScript如何校验值匹配指定类型且不丢失原有推导类型
方案1:使用 TS 4.9+ 内置的 satisfies 操作符(推荐)
这个操作符就是为该场景设计的,作用是仅校验值是否符合目标类型的要求,不会覆盖值本身的类型推导,用法如下:
const fruitMenu = <const>{ "apple": "pie", "banana": "split", "strawberry": "ice", } satisfies Record<string, string>; // 正常推导为 "apple" | "banana" | "strawberry" type Fruits = keyof typeof fruitMenu; // 正常推导为 "pie" | "split" | "ice" type FoodTypes = typeof fruitMenu[Fruits]; function getFoodType(fruit: Fruits): FoodTypes { return fruitMenu[fruit]; } // 错误示例:定义阶段直接触发类型错误,提示数字键/值不符合要求 const fruitMenu2 = <const>{ "apple": "pie", "banana": "split", "strawberry": "ice", 0: 2, } satisfies Record<string, string>;
方案2:低版本TS兼容的泛型工具函数
如果你的项目使用的TS版本低于4.9,可以通过一个通用的泛型函数实现完全相同的效果:
// 通用类型校验工具函数,仅做类型校验不修改原始推导类型 const satisfiesType = <T,>() => <U extends T>(value: U) => value; // 先绑定要校验的目标类型 Record<string, string> const checkStringRecord = satisfiesType<Record<string, string>>(); const fruitMenu = checkStringRecord(<const>{ "apple": "pie", "banana": "split", "strawberry": "ice", }); // 类型推导效果和方案1完全一致 type Fruits = keyof typeof fruitMenu; type FoodTypes = typeof fruitMenu[Fruits];
两种方案均满足需求:
- 定义对象阶段自动校验是否符合指定类型要求,非法结构直接抛出类型错误
- 完全保留值本身的字面量类型,不会被拓宽为声明的通用类型
- 不需要重复编写任何键名、类型定义,符合DRY原则
内容的提问来源于stack exchange,提问作者Zomono
相关产品推荐
相关产品推荐

