cor*_*vid 5 javascript typescript reactjs
我有一个组件,它根据特定属性呈现不同的元素,称为type. 它可以有这样的类型定义:
interface CommonProps {
size: 'lg' | 'md' | 'sm';
}
interface SelectInputProps extends CommonProps {
type: 'select';
options: readonly Option[];
selected: string;
}
interface TextInputProps extends CommonProps {
type: 'text';
value: string;
};
type InputProps = (SelectInputProps | TextInputProps) & ExtraProps;
function Field(props: InputProps): JSX.Element;
Run Code Online (Sandbox Code Playgroud)
现在在我自己的组件中,我将访问该组件的属性,如下所示:
import { ComponentProps } from 'react';
type FieldProps = ComponentProps<typeof Field>;
function MySpecialField(props: FieldProps) {
if (props.type === 'select') {
// this works
const { options, selected } = props;
}
return <Field {...props} />
}
Run Code Online (Sandbox Code Playgroud)
这绝对没问题。它知道我所在的if街区props是SelectInputProps。然而,我做了一个小小的改变,它似乎完全打破了这种使用受歧视联盟的模式。
type FieldProps = Omit<ComponentProps<typeof Field>, 'size'>;
Run Code Online (Sandbox Code Playgroud)
为什么会发生这种情况?有办法解决吗?
这是因为实用程序Omit<T, K>类型不会分布在. 该实现使用,并且当是联合时,仅是联合所有成员中存在的那些键(在 中是逆变的,因此相当于)。这按照microsoft/TypeScript#31501 的预期工作。Tkeyof TTkeyof Tkeyof TTkeyof (A | B)(keyof A) & (keyof B)
幸运的是,如果您想要 的分布式版本,您可以使用分布式条件类型Omit自己编写:
type DistributiveOmit<T, K extends PropertyKey> =
T extends any ? Omit<T, K> : never;
Run Code Online (Sandbox Code Playgroud)
然后你可以看到行为的变化:
type MyFieldProps = DistributiveOmit<React.ComponentProps<typeof Field>, 'a'>;
/* type MyFieldProps = Omit<{
type: 'select';
options: Option[];
} & ExtraProps, "a"> | Omit<{
type: 'text';
value: string;
} & ExtraProps, "a"> */
Run Code Online (Sandbox Code Playgroud)
这使您的代码开始工作:
function MyField(props: MyFieldProps) {
if (props.type === 'select') {
const options = props.options; // okay
}
return <input />
}
Run Code Online (Sandbox Code Playgroud)
function MyField(props: MyFieldProps) {
if (props.type === 'select') {
// Here's the problem
const options = props.options;
}
return <input />
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
899 次 |
| 最近记录: |