如果缺少 prop,React Typescript 会区分类型

发布于 2025-01-12 13:07:31 字数 2297 浏览 0 评论 0原文

我正在尝试创建一个带有可清除属性的选择,该属性允许单击可清除按钮,单击该按钮时会调用 onChange 处理程序,并将 null 作为值。当 clearable 设置为 true 时,我希望将 onChange 处理程序键入为 T |空=> void ,当它设置为 false 时,我希望将其输入为 T =>;无效。这部分不是问题,当我希望 clearable 的默认值为 true 时,问题就出现了,这允许用户在不指定 的情况下调用选择组件clearable 属性并输入 onChange,就好像 clearable 为 true。请参阅下面的代码,并让我知道如何在未设置 clearable 时键入 SelectProps 来正确设置 onChange

type SelectProps<T> = {
  options: T[];
  value: T;
} & (
  | {
      clearable: false;
      onChange: (val: T) => void;
    }
  | {
      clearable?: true;
      onChange: (val: T | null) => void;
    }
);

const Select = <T extends string>({
  options = [],
  value,
  clearable = true,
  onChange,
}: SelectProps<T>): React.ReactElement<SelectProps<T>> => <div>select</div>;

class App extends React.Component {
  render() {
    return (
      <>
        {/*Works, onChange val is typed to string */}
        <Select
          clearable={false}
          options={[]}
          value=""
          onChange={(val) => console.log(val)}
        />

        {/*Works, onChange val is typed to string OR null */}
        <Select
          clearable={true}
          options={[]}
          value=""
          onChange={(val) => console.log(val)}
        />

        {/* Doesn't Work, onChange val is typed to any */}
        <Select options={[]} value="" onChange={(val) => console.log(val)} />
      </>
    );
  }
}

请注意,以下操作均无效:

{
  clearable: false;
  onChange: (val: T) => void;
} | {
  clearable: true | undefined;
  onChange: (val: T | null) => void;
}

// Or using a separated "undefined" case...
{
  clearable: false;
  onChange: (val: T) => void;
} | {
  clearable: true;
  onChange: (val: T | null) => void;
} | {
  clearable: undefined;
  onChange: (val: T | null) => void;
}


// Or defining a case without the "clearable" prop
{
  clearable: false;
  onChange: (val: T) => void;
} | {
  clearable: true;
  onChange: (val: T | null) => void;
} | {
  onChange: (val: T | null) => void;
}

I am trying to create a select with a clearable prop which allows a clearable button to be clicked, which when clicked calls the onChange handler with null as the value. When clearable is set as true I want onChange handler to be typed as T | null => void and when it is set to false I want it to be typed as just T => void. That part is not a problem, the problem arises when I want the default value for clearable to be true which allows the user to call the select component without specifying the clearable prop and have the onChange typed as if clearable was true. Please see code below and let me know how to type the SelectProps to set the onChange properly when clearable is not set.

type SelectProps<T> = {
  options: T[];
  value: T;
} & (
  | {
      clearable: false;
      onChange: (val: T) => void;
    }
  | {
      clearable?: true;
      onChange: (val: T | null) => void;
    }
);

const Select = <T extends string>({
  options = [],
  value,
  clearable = true,
  onChange,
}: SelectProps<T>): React.ReactElement<SelectProps<T>> => <div>select</div>;

class App extends React.Component {
  render() {
    return (
      <>
        {/*Works, onChange val is typed to string */}
        <Select
          clearable={false}
          options={[]}
          value=""
          onChange={(val) => console.log(val)}
        />

        {/*Works, onChange val is typed to string OR null */}
        <Select
          clearable={true}
          options={[]}
          value=""
          onChange={(val) => console.log(val)}
        />

        {/* Doesn't Work, onChange val is typed to any */}
        <Select options={[]} value="" onChange={(val) => console.log(val)} />
      </>
    );
  }
}

Note, none of the following work:

{
  clearable: false;
  onChange: (val: T) => void;
} | {
  clearable: true | undefined;
  onChange: (val: T | null) => void;
}

// Or using a separated "undefined" case...
{
  clearable: false;
  onChange: (val: T) => void;
} | {
  clearable: true;
  onChange: (val: T | null) => void;
} | {
  clearable: undefined;
  onChange: (val: T | null) => void;
}


// Or defining a case without the "clearable" prop
{
  clearable: false;
  onChange: (val: T) => void;
} | {
  clearable: true;
  onChange: (val: T | null) => void;
} | {
  onChange: (val: T | null) => void;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文