Definitelytyped: react-select: Select.onChange typings erradas (?)

Criado em 28 jan. 2019  ·  12Comentários  ·  Fonte: DefinitelyTyped/DefinitelyTyped

https://github.com/DefinitelyTyped/DefinitelyTyped/blob/6f8151b70381d83a6b7e2fc1a44086047144eb9e/types/react-select/lib/Select.d.ts#L166

Eu acredito que isso deve ser definido como:

onChange?: (value: OptionType | OptionType[], action: ActionMeta) => void;

Quando uma opção é selecionada, o objeto de opção bruto é enviado, não o ValueType desse objeto.

Comentários muito úteis

Como faço para usar a definição atual sem erros do compilador?

Screen Shot 2020-01-10 at 4 50 20 PM

Parece que a verificação isArray não é mais suficiente, pois o tipo não é OptionType | OptionType[] e o typescript não pode inferi-lo.

Todos 12 comentários

Eu achei isso totalmente confuso.

value no identificador é a matriz de opções selecionadas (ao usar isMuli prop).

_onTagChange(
  value: ReactSelectTypes.ValueType<{value: number; label: string}>,
  action: ReactSelectTypes.ActionMeta
) {
  console.log('l68:', value, ' action:', action);
  switch(action.action) {
    case 'pop-value':
    case 'remove-value':
  }
  if (value && value.length > 0) {
   e let firstOption = value[0]; // Errors here with: Element implicitly has an 'any' type because type '{ value: number; label: string; } | { value: number; label: string; }[]' has no index signature.

  }
  // this.setState({ categoryTags: tags });
}

O primeiro argumento do manipulador onChange não pode ser simplesmente do tipo OptionType , pois pode ser um, vários ou nenhum valor de OptionType .

Consulte https://github.com/JedWatson/react-select/issues/2902 para uma discussão mais aprofundada sobre o manipulador onChange em combinação com TypeScript.

@rvanlaarhoven - Atualizado OP para aceitar um ou array. IMO, um array deve ser passado para o manipulador independentemente de o select isMulti . Devemos apenas esperar um array e não ter que verificar se o parâmetro é um array. Mas tudo bem ...

Eu concordo com @JoshMcCullough
Seria mais fácil se tivéssemos que lidar apenas com um único tipo de dados, neste caso, Arrays.
Se estivermos usando seleção única, apenas pegamos o único item do array, caso contrário, trabalharemos com o array - sem verificações extras necessárias. Ao mesmo tempo, entendo que não seja uma mudança simples ao lidar com uma biblioteca como esta.

O maior aborrecimento para mim é que um array ou valor único é retornado dependendo do valor de isMulti . Isso significa que o sistema de tipos já deve saber o tipo de onChange .

Podemos fazer algum tipo de união ou tipagem condicional para resolver isso? (aviso: ideias não testadas)

interface BaseProps<OptionType extends OptionTypeBase = { label: string; value: string }> extends SelectComponentsProps {
  ... /* all existing fields except isMulti and onChange */
}

interface SingleValueProps<...> extends BaseProps<...> {
  isMulti: false;
  onChange: (value: OptionType | null | undefined, action: ActionMeta) => void;
}

interface MultiValueProps<...> extends BaseProps<...> {
  isMulti: true;
  onChange: (value: OptionsType<OptionType> | null | undefined, action: ActionMeta) => void;
}

/* where the props are defined */
selectProps: SingleValueProps<...> | MultiValueProps<...>

ou talvez

interface Props<IsMulti extends boolean, OptionType extends OptionTypeBase = { label: string; value: string }> extends SelectComponentsProps {
  ...
  isMulti: IsMulti,
  onChange: (value: ValueType<IsMulti, OptionType>, action: ActionMeta) => void;
  ...
}

export type ValueType<IsMulti extends boolean, OptionType extends OptionTypeBase> =
  (IsMulti extends false ? OptionType : OptionsType<OptionType>) | null | undefined;

EDITAR: depois de pensar um pouco mais sobre isso, o tipo é deduzível se você codificar isMulti (por exemplo, <Select isMulti={false} /> mas não se você fornecer uma declaração como <Select isMulti={getValue()} /> , então esta estratégia provavelmente não funcionará.

Como faço para usar a definição atual sem erros do compilador?

Screen Shot 2020-01-10 at 4 50 20 PM

Parece que a verificação isArray não é mais suficiente, pois o tipo não é OptionType | OptionType[] e o typescript não pode inferi-lo.

Usei uma declaração de tipo como uma solução alternativa aqui:

props.onChange((v as YourOptionTypeHere).value);

Há uma interface (Typescript) disponível para o valor múltiplo undefined, Array<Option>, Option ?

@hoetmaaiers Você poderia fazer um ajudante:

type Nullable<T> = T | null | undefined;

Como solução alternativa, defini uma interface:
interface iOption { label: string; value: string; };

E então, lançou o parâmetro:
onChange={(option) => myMethod((option as iOption).value) }

usar as anula todo o propósito de usar o texto digitado. Quem sou eu para tirar o valor de um

option: ValueType<{value :string, label: string}>

sem usar as ? a solução alternativa atual não é uma solução e pode (provavelmente irá) levar a bugs no futuro.

Ainda estou tendo esse problema e é realmente irritante fazer em cada onChange (porque não estou usando nenhuma seleção múltipla) para converter para o tipo de opção única ....

Sempre que devo usar item => (item como OptionTypeBase) .value. Muito ruim.

Esta página foi útil?
0 / 5 - 0 avaliações