如何在typescript中为React-Select定义onChange处理程序

时间:2017-12-11 20:43:18

标签: typescript react-select

我无法让onchange函数输入正确。我创建了一个处理函数,但是typescript一直在抱怨类型不匹配。

我的功能:

private handleChange(options: Array<{label: string, value: number}>) {
}

打字稿错误:

src/questionnaire-elements/AssessmentFactorSearch.tsx (43,9): Type '{ ref: "select"; name: string; backspaceToRemoveMessage: ""; value: { label: string; value: IAsse...' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<Async<OptionValues>> & Readonly<{ children?: React...'. Type '{ ref: "select"; name: string; backspaceToRemoveMessage: ""; value: { label: string; value: IAsse...' is not assignable to type 'Readonly<ReactAsyncSelectProps<OptionValues>>'. Types of property 'onChange' are incompatible. Type '(options: { label: string; value: number; }[]) => void' is not assignable to type 'OnChangeHandler<OptionValues, Option<OptionValues> | Option<OptionValues>[]> | undefined'. Type '(options: { label: string; value: number; }[]) => void' is not assignable to type 'OnChangeHandler<OptionValues, Option<OptionValues> | Option<OptionValues>[]>'. (2322)

如何输入onchange方法?

3 个答案:

答案 0 :(得分:5)

至于react,请选择 ˆ3.1.0 ,下面的代码应该起作用:

import {ValueType, ActionMeta} from 'react-select';

type MyOptionType = { label: string, value: number }

type OnChange = (value: ValueType<MyOptionType>, actionMeta: ActionMeta<MyOptionType>) => void;

答案 1 :(得分:1)

也遇到了这个问题,找不到有关打字稿和react-select用法的任何示例。所以我将在这里发表我的建议。

之前:我的版本是react-select": "1.2.1"。我想,您已经安装了@types/react-select类型定义。如您所见here,已经有v2的beta版本。他们声称已经简化了API,因此可以选择。我仍然坚持使用v1,因为那里还没有任何v2打字稿@types。

假设我们已经定义了Select组件:

<Select
        name="columns-select"
        value={selectedOptions}
        multi={true}
        onChange={this.onChange.bind(this)}
        options={options}
    />

当您检查onChange的方法签名时:

onChange?: OnChangeHandler<TValue>; 

export type OnChangeHandler<TValue = OptionValues, TOption 
 = Option<TValue> | Options<TValue>> = (newValue: TOption | null) => void;

您会看到泛型和Union type的组合不断出现。

有效地说,返回类型可以是Option[] | Option | nullOption是您的label value对,其中value可以是string|number|boolean(由通用类型变量TValue的默认值定义)。

因此,IMO解决此构造的唯一选择是使用某种Type Guards

在我的情况下,我只想始终拥有选定的string值的数组,因此我将类型强制转换为编译器的数组,并将string|number|boolean视为纯字符串。

import Select, { Options, OnChangeHandler, Option, OptionValues } from 'react-select';

onChange<TValue = OptionValues,
        TOption = Option<TValue> | Options<TValue>>(newValue: TOption | null): void {
        if (Array.isArray(newValue)) {
            this.props.myParentHandlerFunc(
              newValue.map((option: Option) => String(option.value)));
        }
        else {
            throw new Error(`React-select options format wrong. 
            Expected array of changed selections.`);
        }
    }

在定义组件时,您可能可以进一步限制TValue泛型类型变量。例如。

let StringSelect: new() => React.Component<ReactSelectProps<string>> = Select;

,并在JSX中将Select补偿用作StringSelect。有关更多信息,您可以签出Generics Components with JSX(对它进行测试)。

希望,会有所帮助。

答案 2 :(得分:1)

基于https://github.com/JedWatson/react-select/issues/2902,只需编写这样的处理程序即可:

// define your option type
type MyOption = {label: string, value: number}

// ...

  // define your onChange handler:
  private handleChange = (selected?: MyOption | MyOption[] | null) => {
    /** Code **/
  }

记下MyOption | MyOption[] | null部分,该部分与react-select库中onChange的定义具有相同的结构。只需输入您自己的MyOption类型即可。

该问题线程中的另一个示例还显示,您可以内联传递函数,在这种情况下,将自动推断处理程序参数的类型:

<Select
  onChange={selectedOption /* type is automatically inferred here */ => {
    if (Array.isArray(selectedOption)) {
      throw new Error("Unexpected type passed to ReactSelect onChange handler");
    }

    doSomethingWithSelectedValue(selectedOption.value);
  }}
  ...
/>