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

如何基于两个泛型类型与布尔值抛出TypeScript错误

实现TypeScript泛型配置的类型约束规则

核心思路

通过自定义类型工具和条件类型,根据someBoolean、泛型T和R的组合,在编译阶段对不符合规则的配置抛出错误。

步骤1:定义类型判断工具

先创建三个基础类型工具,用来区分泛型属于规则中的string、number还是object(非原始引用类型):

// 判断是否为 string 类型
type IsString<T> = T extends string ? true : false;
// 判断是否为 number 类型
type IsNumber<T> = T extends number ? true : false;
// 判断是否为引用类型(对应规则中的 object 类别)
type IsObject<T> = T extends string | number ? false : true;

步骤2:方案一:用条件类型直接约束配置

通过ValidConfig条件类型,根据someBoolean的取值分支实现规则判断,不符合规则的分支返回never类型,触发编译错误:

interface BaseConfig<T, R> {
  someBoolean: boolean;
}

type ValidConfig<T, R, B extends boolean> = 
  // someBoolean 为 false 时的规则
  B extends false 
    ? (IsString<T> extends true 
      ? IsString<R> extends true ? BaseConfig<T, R> : never 
      : IsNumber<T> extends true 
        ? IsNumber<R> extends true ? BaseConfig<T, R> : never 
        : IsObject<T> extends true 
          ? (IsString<R> extends true || IsNumber<R> extends true ? BaseConfig<T, R> : never) 
          : never)
    // someBoolean 为 true 时的规则
    : (IsString<T> extends true 
      ? IsString<R> extends true ? BaseConfig<T, R> : never 
      : IsNumber<T> extends true 
        ? IsNumber<R> extends true ? BaseConfig<T, R> : never 
        : IsObject<T> extends true ? BaseConfig<T, R> : never);

// 合法示例
const valid1: ValidConfig<string, string, false> = { someBoolean: false };
const valid2: ValidConfig<{ name: string }, number, false> = { someBoolean: false };
const valid3: ValidConfig<{ name: string }, { age: number }, true> = { someBoolean: true };

// 非法示例(编译报错)
// const invalid1: ValidConfig<string, number, false> = { someBoolean: false };
// const invalid2: ValidConfig<{ name: string }, { age: number }, false> = { someBoolean: false };

步骤3:方案二:用允许组合元组约束

把所有允许的组合整理成元组联合类型,通过判断当前组合是否在允许列表中来约束配置,维护更直观:

// 定义所有允许的组合([someBoolean, T, R])
type AllowedCombinations = 
  [false, string, string] |
  [false, number, number] |
  [false, object, string] |
  [false, object, number] |
  [true, string, string] |
  [true, number, number] |
  [true, object, string] |
  [true, object, number] |
  [true, object, object];

// 判断当前组合是否合法
type IsAllowed<B extends boolean, T, R> = [B, T, R] extends AllowedCombinations ? true : false;

// 配置接口,通过_guard属性触发错误
interface IConfig<B extends boolean, T, R> {
  someBoolean: B;
  // 不合法时_guard类型为never,无法赋值
  _guard: IsAllowed<B, T, R> extends true ? unknown : never;
}

// 合法示例
const validConfig: IConfig<false, string, string> = { someBoolean: false, _guard: undefined };

// 非法示例(编译报错)
// const invalidConfig: IConfig<false, string, number> = { someBoolean: false, _guard: undefined };

关键说明

  • 方案一适合需要动态逻辑的约束,方案二更适合规则固定、需要直观维护的场景。
  • IsObject类型会把所有非string/number的类型(包括接口、自定义对象、数组等)判定为规则中的object类别,符合需求。

内容的提问来源于stack exchange,提问作者Andrew Allen

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 13:50:28