Почему я не могу использовать Omit на AsyncProps реагировать на выбор? - PullRequest
0 голосов
/ 11 марта 2020

Я пытался обернуть компонент SelectSearchResult вокруг AsyncSelect из react-select. Я бы хотел, чтобы реквизиты моего пользовательского компонента были почти такими же, как у AsyncSelect, за некоторыми исключениями.

import AsyncSelect, { Props as AsyncSelectProps } from "react-select/async";

// works, but Props allows all properties
type Props = AsyncSelectProps<{ label: string; value: string }>;

const SelectSearchResult = (props: Props) => {
    return <AsyncSelect {...props} />;
};

Я предположил, что мне просто нужно опустить ключи, которые мне не нужны.

type Props = Omit<AsyncSelectProps<{ label: string; value: string }>, "loadOptions">;

Однако, когда я проверяю Props, он теперь имеет следующий формат, и я Я не знаю, почему он принимает эту форму.

type Props = {
  [x: string]: any;
  [x: number]: any;
}

Ответы [ 2 ]

0 голосов
/ 23 марта 2020

После долгих поисков я обнаружил, что проблема на самом деле заключается в том, как определяется AsyncProps, потому что в его теле находится индексная сигнатура, которая заставляет Exclude или Omit работать неправильно.

Чтобы проиллюстрировать проблему:

// This type accepts the known keys `a` and `b` as strings and anything 
// else with unknown keys
type MyType = {
    a: string;
    b: string;
    [key: string]: any; // index signature
};

type MyTypeWithoutA = Omit<MyType, "a">;

// I expected the object below to complain for the fact, that "b" is not defined
// but it doesn't happen
const obj: MyTypeWithoutA = {}; 

Решение, которое я нашел, состояло в том, чтобы сначала получить производный тип MyType без подписи индекса и создать альтернативную версию Omit

type KnownKeys<T> = {
    [K in keyof T]: string extends K ? never : number extends K ? never : K
} extends { [_ in keyof T]: infer U } ? U : never;

// K is the union of keys I want to omit from the known keys of T
type OmitKnownKeys<T, K extends string> = Omit<Pick<T, KnownKeys<T>>, K>;

Переписать код на

type MyTypeWithoutA = OmitKnownKeys<MyType, "a">;

const obj: MyTypeWithoutA = {}; // error, b is not defined (what I wanted)

Важно : это решение работает для моего конкретного c случая, но фактически удаляет сигнатуру индекса из вашего типа делая его менее гибким, другими словами, вы не можете передавать аргументы, которые будут соответствовать сигнатуре индекса. Отметьте эту версию , если хотите сохранить подпись индекса.

Источники: 1 , 2

0 голосов
/ 11 марта 2020

Вы можете использовать тип never и оператор &. Например: type Props =AsyncSelectProps<{ label: string; value: string }> & {loadOptions: never };

Когда кто-то попытается позвонить Props.loadOptions, он вернет never и никогда не будет назначен никаким типам, поэтому это вызовет ошибку при следующем использовании.

...