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

如何使用可选判别器收窄TypeScript可辨识联合类型?

解决TypeScript可辨识联合类型的收窄问题

问题背景

我正在实现一个类React Select的组件,通过可选的isMulti布尔值支持单选/多选(未提供时默认false),采用可辨识联合类型定义Props,但在调用onChange时TypeScript无法正确推断参数类型,报错如下:

Argument of type 'OptionValue | OptionValue[]' is not assignable to parameter of type 'OptionValue & OptionValue[]'.
Type 'OptionValue' is not assignable to type 'OptionValue & OptionValue[]'.
Type 'OptionValue' is missing the following properties from type 'OptionValue[]': length, pop, push, concat, and 26 more.

核心原因

单独提取props.value后,它与isMulti的类型关联被切断,TypeScript无法将value和onChange的类型匹配起来——此时onChange是两种函数类型的联合,要求参数必须同时满足两种类型的交集,导致报错。

解决方案

方案1:通过isMulti直接收窄整个Props类型

保持isMulti、value、onChange的类型关联,通过检查props.isMulti来收窄Props的具体类型,TypeScript会自动推断对应value和onChange的类型:

type OptionValue = {
  label: string;
  value: string;
}

interface CommonProps {
  className?: string;
  disabled?: boolean;
  options: OptionValue[];
}

interface SingleValueProps extends CommonProps {
  isMulti?: false;
  value: OptionValue | null;
  onChange: (value: OptionValue) => void;
}

interface MultiValueProps extends CommonProps {
  isMulti: true;
  value: OptionValue[];
  onChange: (value: OptionValue[]) => void;
}

export type Props = SingleValueProps | MultiValueProps;

function Component(props: Props) {
  function handleChange() {
    if (props.isMulti) {
      // 此处Props被收窄为MultiValueProps类型
      props.onChange(props.value);
    } else {
      // 此处Props被收窄为SingleValueProps类型
      const selectedValue = props.value;
      if (selectedValue != null) {
        props.onChange(selectedValue);
      }
    }
  }

  // 组件渲染逻辑
}

// 测试用例
Component({
  isMulti: true,
  value: [],
  onChange: (value) => console.log("多选值:", value),
  options: []
})

Component({
  isMulti: false,
  value: {label: "选项1", value: "opt1"},
  onChange: (value) => console.log("单选值:", value),
  options: []
})

Component({
  value: {label: "选项1", value: "opt1"},
  onChange: (value) => console.log("单选值(默认):", value),
  options: []
})

方案2:自定义类型守卫(按需使用)

如果需要单独处理value,可以编写自定义类型守卫来明确Props的类型:

// 自定义类型守卫
function isMultiProps(props: Props): props is MultiValueProps {
  return props.isMulti === true;
}

function Component(props: Props) {
  const selectedValue = props.value;

  function handleChange() {
    if (isMultiProps(props)) {
      props.onChange(selectedValue); // 自动推断为OptionValue[]
    } else {
      if (selectedValue != null) {
        props.onChange(selectedValue); // 自动推断为OptionValue
      }
    }
  }
}

关键要点

必须保持可辨识联合中各个属性的类型关联,不能单独提取某一属性后脱离辨识符(isMulti)的约束,否则TypeScript无法完成类型匹配。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 04:44:56