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

如何在TypeScript中缩小可选值的类型范围?

解决TypeScript中根据text属性精准收窄value类型的问题

问题核心是Array.prototype.find的默认回调无法让TypeScript自动识别返回的是联合类型中的特定成员,需要通过类型守卫帮TS明确类型。

两种实现方式:

方式一:自定义可复用的类型守卫函数

先定义一个通用的类型守卫,用来判断选项的text属性是否匹配指定值,同时告诉TS对应的类型:

function isSelectOptionWithText<T extends SelectOption['text']>(
  option: SelectOption,
  text: T
): option is Extract<SelectOption, { text: T }> {
  return option.text === text;
}

然后在find中调用这个函数:

const numberValue = options?.find(option => isSelectOptionWithText(option, 'b'))?.value;

此时numberValue的类型会被自动收窄为number | undefined。

方式二:直接在find回调中使用类型谓词

如果不需要复用,也可以直接在find的回调里写类型谓词,省去单独定义函数的步骤:

const numberValue = options?.find(
  (option): option is Extract<SelectOption, { text: 'b' }> => option.text === 'b'
)?.value;

效果和方式一完全一致,numberValue类型为number | undefined。

完整修改后的代码

import "./styles.css";

type SelectOption =
  | {
      text: "a";
      value: string;
    }
  | {
      text: "b";
      value: number;
    };

type MultySelectOption =
  | {
      text: "c";
      value: boolean;
    }
  | {
      text: "d";
      value: Record<string, string>;
    };

type OptionsBy<T extends string> = T extends "select"
  ? SelectOption[]
  : T extends "multiSelect"
  ? MultySelectOption[]
  : never;

// 可选:自定义类型守卫函数
function isSelectOptionWithText<T extends SelectOption['text']>(
  option: SelectOption,
  text: T
): option is Extract<SelectOption, { text: T }> {
  return option.text === text;
}

export default function App() {
  const options: OptionsBy<"select"> = [];
  
  // 选一种方式使用即可
  const numberValue = options?.find(option => isSelectOptionWithText(option, 'b'))?.value;
  // const numberValue = options?.find(
  //   (option): option is Extract<SelectOption, { text: 'b' }> => option.text === 'b'
  // )?.value;

  const sum = () => {
    return numberValue + 10; // 此处不再有类型报错
  };

  return <div className="App"></div>;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 06:24:51