首页 > 解决方案 > 为什么我不能在 react-select 的 AsyncProps 上使用 Omit?

问题描述

SelectSearchResult我一直在尝试AsyncSelectreact-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;
}

标签: reactjstypescriptreact-select

解决方案


经过大量搜索,我发现问题实际上在于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)

重要提示:此解决方案适用于我的特定情况,但它实际上从您的类型中删除了索引签名,使其不太灵活,换句话说,您无法传递任何与索引签名匹配的参数。如果要保留索引签名,请检查此版本。

来源1、2 _


推荐阅读