TypeScript如何约束属性值为数组指定元素并支持运行时校验
TypeScript 限定属性取值范围+运行时校验实现
你可以通过常量断言+数组元素类型提取+类型谓词的方案,同时满足编译时类型约束和运行时合法性校验,代码如下:
// 1. 给允许值数组加as const断言,将其类型推导为精确的只读元组 readonly ["a", "b"],而非宽泛的string[] export const operationTypes = ["a", "b"] as const; // 2. 提取数组所有元素的字面量类型组成联合类型,等价于 type OperationType = "a" | "b" // 后续修改operationTypes的元素时,这个类型会自动同步,不需要手动维护两份定义 export type OperationType = typeof operationTypes[number]; // 3. 编译时约束:Operation的type属性只能是联合类型里的合法值 export type Operation = { type: OperationType } // 4. 运行时校验:用类型谓词收窄类型,校验通过后TS会自动识别入参为合法Operation类型 function validateOperationType(operation: unknown): operation is Operation { // 先过滤非对象、null的异常输入,避免访问属性时报错 if (typeof operation !== "object" || operation === null) { return false; } const op = operation as Record<string, unknown>; // 校验type字段是否在允许值列表内 return typeof op.type === "string" && operationTypes.includes(op.type as OperationType); }
关键说明
- 不要省略
as const:如果不加这个断言,TS会把operationTypes的类型推导为string[],就没法提取出精确的字面量联合类型,编译时的约束就失效了。 - 类型谓词
operation is Operation比普通的boolean返回值更实用:当函数返回true时,TS会自动把入参的类型收窄为Operation,后续代码操作属性时不会报类型错误。 - 入参用
unknown比直接传Operation更严谨:运行时校验的场景大多是处理JSON反序列化、接口返回的未知结构数据,这些数据在校验前是不满足Operation类型的,从unknown开始逐层校验才能覆盖所有异常情况。 - 校验逻辑里加了
typeof op.type === "string"的判断,避免传入的type不是字符串类型时,includes判断出现不符合预期的结果。
内容的提问来源于stack exchange,提问作者birgersp
相关产品推荐
相关产品推荐

