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

使用io-ts实现泛型品牌类型是否可行?

实现方案:基于io-ts的泛型令牌类型

你的需求是可行的,核心思路是通过泛型品牌标记将令牌字符串与返回类型关联,同时保留io-ts的运行时验证能力。以下是调整后的实现代码:

1. 定义泛型品牌标记

首先创建一个带泛型的品牌接口,用于在类型层面关联令牌对应的返回类型:

import * as t from 'io-ts';

// 泛型品牌标记,携带令牌对应的返回类型信息
interface TokenNameBrand<T> {
  readonly TokenName: unique symbol;
  readonly Type: T;
}

2. 创建io-ts运行时验证器

运行时层面,我们只需要验证输入是字符串(因为你允许任意合法字符串作为令牌),所以品牌验证逻辑保持简单:

// 运行时的io-ts brand类型,不涉及泛型T
const TokenNameRuntime = t.brand(
  t.string,
  (n: unknown): n is t.Branded<string, TokenNameBrand<unknown>> =>
    typeof n === 'string', // 任意字符串都符合令牌要求
  'TokenName'
);

// 泛型类型别名,将令牌字符串与返回类型T绑定
export type TokenName<T> = t.Branded<string, TokenNameBrand<T>>;

3. 创建类型化令牌常量

通过类型断言将字符串转换为带泛型的令牌类型:

const WEIGHT = "weight" as TokenName<number>;
const SPECIES = "species" as TokenName<string>;

4. 实现类型安全的evaluateToken函数

借助映射类型确保令牌与返回类型的一致性,让TypeScript自动推断返回类型:

// 定义令牌到值的映射,确保类型匹配
type TokenValueMap = {
  weight: number;
  species: string;
};

function evaluateToken<K extends keyof TokenValueMap>(
  name: TokenName<TokenValueMap[K]>
): TokenValueMap[K] | null {
  const tokenValues: TokenValueMap = {
    weight: 1200,
    species: "bear"
  };
  // 类型断言:因为我们控制了令牌的创建,name一定是TokenValueMap的key
  return tokenValues[name as keyof TokenValueMap] ?? null;
}

验证效果

此时调用evaluateToken会自动推断正确的返回类型:

const w = evaluateToken(WEIGHT); // w的类型被推断为 number | null
const s = evaluateToken(SPECIES); // s的类型被推断为 string | null

关键说明

  • 运行时:io-ts的TokenNameRuntime负责验证令牌是合法字符串,确保输入符合基本要求。
  • 类型层面:通过泛型TokenName<T>将令牌与返回类型绑定,结合TokenValueMap确保令牌和值的类型一一对应。
  • 可控性:由于你负责令牌的创建(如WEIGHT、SPECIES),只要保证令牌名称与TokenValueMap的key一致,就能维持类型安全。

内容的提问来源于stack exchange,提问作者Michael Lorton

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 13:48:22