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

如何基于部分已知判别式收窄TypeScript可辨识联合类型?

解决React Hook返回值根据功能开关自动收窄类型的方案

核心思路是用泛型捕获入参的具体类型,配合条件类型推导返回值结构,让TypeScript能把入参的功能开关状态和返回值属性做关联,而非依赖可辨识联合的自动收窄(联合类型本身无法在函数内部关联入参和返回的分支)。

步骤1:定义基础类型与工具类型

先拆分基础参数、各功能专属参数,再编写工具类型根据入参开关状态生成对应返回类型:

// 基础共享参数
type BaseArgs = {
  sharedProp: string;
};

// FeatureOne开启时的专属必填参数
type FeatureOneEnabledArgs = {
  isFeatureOneEnabled: true;
  featureOneProp: string;
};

// FeatureOne关闭时的参数(开关可选或设为false)
type FeatureOneDisabledArgs = {
  isFeatureOneEnabled?: false;
};

// 入参的泛型约束:合并基础参数与对应功能分支
type CustomHookArgs<T extends boolean | undefined = undefined> = BaseArgs & 
  (T extends true ? FeatureOneEnabledArgs : FeatureOneDisabledArgs);

// 根据入参开关推导返回值的工具类型
type CustomHookReturn<T extends CustomHookArgs> = {
  sharedState: number;
} & (T extends { isFeatureOneEnabled: true } ? {
  someFeatureOneThings: string;
} : {});

步骤2:用泛型实现Hook

通过泛型捕获调用时的具体入参类型,让返回值自动匹配推导结果:

import { useState } from 'react';

function useCustomHook<T extends CustomHookArgs>(args: T): CustomHookReturn<T> {
  const [sharedState] = useState(0);

  if (args.isFeatureOneEnabled) {
    return {
      sharedState,
      someFeatureOneThings: args.featureOneProp.toUpperCase()
    } as CustomHookReturn<T>;
  }

  return {
    sharedState
  } as CustomHookReturn<T>;
}

步骤3:调用验证

传入不同开关状态时,返回值会自动收窄类型,无需额外条件判断:

// 开启FeatureOne:返回值明确包含someFeatureOneThings,类型为string
const { sharedState, someFeatureOneThings } = useCustomHook({
  sharedProp: 'test',
  isFeatureOneEnabled: true,
  featureOneProp: 'foo'
});
console.log(someFeatureOneThings); // 无类型报错

// 关闭FeatureOne:返回值不包含someFeatureOneThings,访问会直接报错
const { sharedState: disabledState } = useCustomHook({
  sharedProp: 'test',
  isFeatureOneEnabled: false
});
// 此处若访问someFeatureOneThings,TypeScript直接提示属性不存在

原方案问题说明

之前用可辨识联合作为入参时,函数返回值只能是所有联合分支的合并类型,TypeScript无法自动关联“当前传入的是联合某一分支”与返回值的对应关系。而泛型可精准捕获调用时的入参类型,配合条件类型就能实现返回值的自动收窄。

内容的提问来源于stack exchange,提问作者Mike Turley

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 02:56:09