如何在编译时严格校验变量是否与指定类型完全匹配?
解决方案
要实现编译期双向类型等价校验,你需要额外引入类型相等判断逻辑,替换原有单向赋值校验的实现。
最终实现代码
// 高精度类型相等判断工具 type StrictEqual<T, U> = (<G>() => G extends T ? 1 : 2) extends (<G>() => G extends U ? 1 : 2) ? true : false; // 严格类型校验函数 function hasExactType<T, U>(value: U & (StrictEqual<T, U> extends true ? U : never)): void {}
效果验证
- 不符合要求的调用直接触发编译报错:
// 编译失败:实际类型为string,与期望的string|boolean范围不匹配 hasExactType<string | boolean>('somestring'); - 类型完全匹配的调用正常通过:
const testVal: string | boolean = Math.random() > 0.5 ? 'test' : false; hasExactType<string | boolean>(testVal); // 编译正常 - 反向校验同样生效,避免期望类型范围小于实际类型:
const testVal: string | boolean = Math.random() > 0.5 ? 'test' : false; // 编译失败:期望类型为string,实际类型是string|boolean,范围不匹配 hasExactType<string>(testVal);
原理解释
你原来的hasType<T>只做了单向协变校验:只要实际值的类型可以赋值给泛型T就会通过,无法校验二者是否完全等价。上面的StrictEqual工具类型利用了TypeScript条件类型在逆变位置的比较逻辑,可以准确识别两个类型的范围、结构是否完全一致,不会出现联合类型宽限、子类型漏判的问题,所有校验逻辑都在编译阶段执行,不会产生任何运行时代码。
如果只需要处理普通场景,不需要兼容any、函数逆变等特殊边界,也可以用简化版实现:
function hasExactType<T, U extends T>(value: U & (T extends U ? U : never)): void {}
内容的提问来源于stack exchange,提问作者dylhunn
相关产品推荐
相关产品推荐

