Ошибки машинописного текста в зависимости от порядка типов в типе объединения в реагировать на выбор - PullRequest
5 голосов
/ 15 января 2020

Я использую react-select (www.react-select.com) с TypeScript и получаю странные ошибки при использовании options prop. Рассмотрим этот код:

import * as React from "react";
import Select, {
  GroupedOptionsType,
  OptionsType
} from "react-select";

type OType =
  | GroupedOptionsType<{ label: string; value: string }>
  | OptionsType<{ label: string; value: string }>
  | undefined;

const options = [
  { label: "test1", value: "test1" },
  { label: "test2", value: "test2" }
] as OType;

const CustomSelect = () => {
  return <Select options={options} />;
};

Typescript показывает это:

No overload matches this call.
  Overload 1 of 2, '(props: Readonly<{ [x: string]: any; [x: number]: any; defaultInputValue?: string | undefined; defaultMenuIsOpen?: boolean | undefined; defaultValue?: ValueType<GroupType<{ label: string; value: string; }>>; ... 62 more ...; tabSelectsValue?: boolean | undefined; }>): StateManager<...>', gave the following error.
    Type 'OType' is not assignable to type 'OptionsType<GroupType<{ label: string; value: string; }>> | GroupedOptionsType<GroupType<{ label: string; value: string; }>> | undefined'.
      Type 'OptionsType<{ label: string; value: string; }>' is not assignable to type 'OptionsType<GroupType<{ label: string; value: string; }>> | GroupedOptionsType<GroupType<{ label: string; value: string; }>> | undefined'.
        Type 'OptionsType<{ label: string; value: string; }>' is not assignable to type 'OptionsType<GroupType<{ label: string; value: string; }>>'.
          Property 'options' is missing in type '{ label: string; value: string; }' but required in type 'GroupType<{ label: string; value: string; }>'.
  Overload 2 of 2, '(props: { [x: string]: any; [x: number]: any; defaultInputValue?: string | undefined; defaultMenuIsOpen?: boolean | undefined; defaultValue?: ValueType<GroupType<{ label: string; value: string; }>>; ... 62 more ...; tabSelectsValue?: boolean | undefined; }, context?: any): StateManager<...>', gave the following error.
    Type 'OType' is not assignable to type 'OptionsType<GroupType<{ label: string; value: string; }>> | GroupedOptionsType<GroupType<{ label: string; value: string; }>> | undefined'.
      Type 'OptionsType<{ label: string; value: string; }>' is not assignable to type 'OptionsType<GroupType<{ label: string; value: string; }>> | GroupedOptionsType<GroupType<{ label: string; value: string; }>> | undefined'.
        Type 'OptionsType<{ label: string; value: string; }>' is not assignable to type 'OptionsType<GroupType<{ label: string; value: string; }>>'.ts(2769)

Но когда я меняю порядок типов в типе объединения и ставлю сначала OptionsType<>, это полностью ОК.

import * as React from "react";
import Select, {
  GroupedOptionsType,
  OptionsType
} from "react-select";

type OType =
  | OptionsType<{ label: string; value: string }>
  | GroupedOptionsType<{ label: string; value: string }>
  | undefined;

const options = [
  { label: "test1", value: "test1" },
  { label: "test2", value: "test2" }
] as OType;

const CustomSelect = () => {
  return <Select options={options} />;
};

AFAIK порядок типов в типе объединения не имеет значения, но я подозреваю, что это может иметь значение при использовании обобщенных элементов, когда происходит разрешение типов, но я не знаю. Странно, я тоже сделал это (то же самое, что и выше, но здесь я беру options непосредственно из SelectProps), и это тоже не получается:

import * as React from "react";
import Select, {
  Props as SelectProps,
} from "react-select";

type OType = Pick<SelectProps<{label: string; value: string}>, 'options'>

const options = [
  { label: "test1", value: "test1" },
  { label: "test2", value: "test2" }
] as OType;

const CustomSelect = () => {
  return <Select options={options} />;
};

1 Ответ

1 голос
/ 24 января 2020

Я изменил ответную реакцию следующим образом, и она работает так, как вы хотите, любым способом. Попробуй это. Я также реализовал «Выбрать все сразу», когда для нескольких реквизитов установлено значение «истина».

import clsx from 'clsx';
import React, { ComponentProps, FC, useState } from 'react';
import ReactSelect from 'react-select';

type Option = string | number;
type Options = { [key in Option]: any };

export interface SelectProps extends ComponentProps<typeof ReactSelect> {
  allowSelectAll?: boolean;
  allOption?: { value: string; label: string };
  options?: Options[];
  onChange?: (Options) => void;
}

const Select: FC<SelectProps> = function ({
  className,
  options,
  onChange,
  allowSelectAll,
  ...props
}) {

  const [allOption, setallOption] = useState({ value: "*", label: "Select All" });

  if (allowSelectAll) {
    return (
      <ReactSelect
        {...props}
        classNamePrefix="custom-select"
        className={clsx("custom-select", className)}
        options={[allOption, ...options]}
        onChange={selected => {
          if (
            selected !== null &&
            selected.length > 0 &&
            selected[selected.length - 1].value === allOption.value
          ) {
            setallOption({ value: "", label: "All Selected" });
            return onChange(options);
          }
          setallOption({ value: "", label: "Select All" });
          return onChange(selected);
        }}
      />

    );
  }

  return (
    <ReactSelect
      {...props}
      options={options}
      onChange={onChange}
      classNamePrefix="custom-select"
      className={clsx("custom-select", className)}
    />
  );


};

export default Select;

...