TypeScript工具类型能否转为字面量类型?如何推导HTTPHost类型?
问题解答
1. 工具类型转换为字面量类型
可以将工具类型(如Equal、Expect)的结果转换为字面量类型,让类型检查反馈更直观,直接返回具体的错误信息字面量,而非仅依赖TypeScript的类型报错。
修改后的工具类型示例:
// 改进后的Equal:不相等时返回错误信息字面量 type Equal<X, Y> = (<T>() => T extends X ? 1 : 2) extends (<T>() => T extends Y ? 1 : 2) ? true : `"${X}" is not equal to "${Y}"`; // 改进后的Expect:接受true或错误字面量,不满足时直接暴露错误信息 type Expect<T extends true | string> = T extends true ? true : T; type ExpectFalse<T extends false | string> = T extends false ? true : `"Expected false but got ${T}"`;
当类型不匹配时,Expect会直接返回具体的错误字面量,比如"something invalid here" is not equal to "aaa",比原有的类型报错更清晰。
2. 推导HTTPHost类型
可以通过递归字符串字面量类型,实现仅由'a'和'b'组成的任意序列的字符串字面量类型:
type HTTPChars = 'a' | 'b'; // 递归定义:单个HTTP字符,或HTTP字符拼接任意HTTPHost type HTTPHost = HTTPChars | `${HTTPChars}${HTTPHost}`;
这个类型会匹配所有由a和b组成的字符串,包括'a'、'b'、'aa'、'ab'、'ba'、'bb'、'aaa'等任意长度的组合(TypeScript对递归深度有一定限制,但日常场景足够覆盖)。
结合原代码的完整测试示例
// 改进后的工具类型 type Equal<X, Y> = (<T>() => T extends X ? 1 : 2) extends (<T>() => T extends Y ? 1 : 2) ? true : `"${X}" is not equal to "${Y}"`; type Expect<T extends true | string> = T extends true ? true : T; type ExpectFalse<T extends false | string> = T extends false ? true : `"Expected false but got ${T}"`; // 自定义类型 type HTTPChars = 'a' | 'b'; type HTTPHost = HTTPChars | `${HTTPChars}${HTTPHost}`; type IsHTTPHost<S extends any, T = S> = S extends HTTPHost ? T : T extends string ? `"${T}" contains illegal characters` : `Provided value must be a string`; // 测试用例(添加as const保留字面量类型) const hostname1 = 'aaa' as const; const hostname2 = 'bbb' as const; const hostname3 = 'something invalid here' as const; const hostname4 = 9 as const; type cases = [ Expect<Equal<typeof hostname1, IsHTTPHost<typeof hostname1>>>, Expect<Equal<typeof hostname2, IsHTTPHost<typeof hostname2>>>, ExpectFalse<Equal<typeof hostname3, IsHTTPHost<typeof hostname3>>>, Expect<Equal<IsHTTPHost<typeof hostname3>, '"something invalid here" contains illegal characters'>>, Expect<Equal<IsHTTPHost<typeof hostname4>, 'Provided value must be a string'>> ];
注意:原代码中hostname变量需要添加as const来保留字符串字面量类型,否则TypeScript会将其推断为string类型,无法进行精确的字面量检查。
内容的提问来源于stack exchange,提问作者mzedeler
相关产品推荐
相关产品推荐

