【发布时间】:2019-10-05 17:41:01
【问题描述】:
我正在编写一个包装 react-select 的 Select 组件的 React 组件,该组件有一个 starts like this 的 prop 声明:
export type SelectComponentsProps = { [key in string]: any };
export interface Props<OptionType extends OptionTypeBase = { label: string; value: string }> extends SelectComponentsProps {
我导入了这个类型,并试图像这样声明我的包装器组件的道具:
import { Props as SelectProps } from "react-select/src/Select";
type Props = Omit<SelectProps, "inputId"> & { ... some other stuff };
但我遇到了一个问题,我可以“安全地”将任何我想要的东西传递给我的组件,即使对于在 SelectProps 上具有显式类型声明的字段:
// okay
<MySelectWrapper onChange="definitely not a function"/>
// not okay, fails type checking
<Select onChange="definitely not a function"/>
经过一番挖掘,我发现Omit 和索引签名的组合(在 react-select 示例中:SelectComponentsProps)导致编译器删除显式指定的字段,而只使用索引签名。
interface ArbitraryKeyable {
foo: number;
[key: string]: any;
}
const value = {
foo: 'not a number',
bar: 'this can be anything'
}
// Fails: foo is the wrong type.
const arbitrary: ArbitraryKeyable = value;
type OmittedArbitraryKeyable = Omit<ArbitraryKeyable, 'this is not a field'>;
// Succeeds, even though the type should functionally be the same.
const omittedArbitrary: OmittedArbitraryKeyable = value;
游乐场认为该类型是这样的:
所以它当然接受一切!有没有办法定义一个保留显式定义字段的Omit 版本?或者,是否可以执行类型操作来删除索引签名并且只有显式字段? (我的用例并不需要它,所以我可以放弃这种灵活性以在其他地方获得类型安全。)
【问题讨论】:
标签: typescript