You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 18:14:58