TypeScript中能否在tsc编译阶段抛出自定义错误拦截非法传参?
实现方案
可以通过TS原生类型系统实现编译期参数校验,无需依赖第三方工具,核心是通过条件类型将非法参数组合排除在入参允许范围之外,不需要在函数体内部做运行时判断,调用时传非法参数会直接触发TS编译报错。
示例1:字符串字面量参数校验
针对你给出的f函数场景,有两种常用实现方式:
方案1:枚举合法参数组合
适合合法参数组合数量较少的场景,直接把所有合法的参数对定义为入参的联合类型:
// 定义所有允许的参数组合 type ValidInput = | ["A", "C"] | ["A", "D"] | ["B", "C"] function f(...args: ValidInput) { const [arg1, arg2] = args // 执行其他业务逻辑 }
调用校验效果:
f("A", "C"); // 正常编译 f("A", "D"); // 正常编译 f("B", "C"); // 正常编译 f("B", "D"); // 编译报错:类型“"D"”的参数不能赋给类型“"C"”的参数
方案2:泛型条件类型排除非法组合
适合参数可选值多、枚举所有合法组合成本高的场景,通过条件类型直接拦截非法组合:
function f<T extends "A" | "B", U extends "C" | "D">( arg1: T, // 如果arg1是"B",则arg2不能为"D",否则类型为never arg2: T extends "B" ? U extends "D" ? never : U : U ) { // 执行其他业务逻辑 }
调用校验效果和方案1完全一致,传f("B", "D")时会因为"D"无法赋值给never类型触发编译报错。
示例2:数值参数校验(旧示例root函数)
针对数值入参的场景,仅对字面量传参有效,如果入参是运行时才能确定值的变量(比如接口返回值、用户输入值),TS编译期无法感知运行时数值,这种场景只能加运行时判断,无法做编译期拦截。
字面量传参的实现如下:
// 辅助类型:判断数值是否为偶数 type IsEven<T extends number> = `${T}` extends `${infer N extends number}` ? N extends 0 ? false : `${N}` extends `${string}${0|2|4|6|8}` ? true : false : false // 辅助类型:判断数值是否为负数 type IsNegative<T extends number> = `${T}` extends `-${number}` ? true : false function root<T extends number, U extends number>( radical: T, // 如果根指数是偶数,则被开方数不能为负数,否则类型为never radicand: IsEven<T> extends true ? IsNegative<U> extends true ? never : U : U ) { // 执行计算逻辑 return Math.pow(radicand, 1/radical) }
调用校验效果:
root(2, 4) // 正常编译 root(2, -4) // 编译报错:类型“-4”的参数不能赋给类型“never”的参数 root(3, -8) // 正常编译
内容的提问来源于stack exchange,提问作者catwith
相关产品推荐
相关产品推荐

