我正在React中构建一个Dropdown
组件。它包含一个options
对象和一个可选的value
对象,它将预先选择给定的options
中的一个。我希望能够键入value
,以便它必须是options
中给定的名称之一。
单个option
如下所示:
interface Option {
name: string;
value: string;
}
该组件的props
如下所示:
interface Props {
options: Option[];
value?: ValidOption; // How can I write ValidOption?
}
是否可以使value
必须是options
数组中的值之一?
例如,给定以下选项:
const options = [
{ name: 'Option1', value: 'option1' },
{ name: 'Option2', value: 'option2' },
]
我希望ValidOption
等于:
type ValidOption = 'option1' | 'option2';
答案 0 :(得分:0)
您的问题类似于this question。您无法定义单一类型Props
来接受{options, value}
形式的对象,其中value
是options
之一。您可以通过为有效选项引入类型参数O
来开始:
interface Option<O extends string> {
name: string;
value: O;
}
interface Props<O extends string> {
options: Option<O>[];
value?: O;
}
但是您遇到两个问题:
Props<O>
代表某些O
”的单一类型。这将是existential type,TypeScript当前不支持。 Props<any>
不起作用:它对选项和值没有任何限制。O
,则无法强制options
包含 all O
的值。鉴于这些问题,最接近的方法是编写一个通用函数,该函数可以使用{options, value}
对象文字进行调用,这样,如果值是选项之一,则类型推断将成功,并且失败如果不是这样。根据您其余代码的结构,此方法可能有用也可能无效。
// Building on `Option` and `Props` defined above.
// Needed to prevent widening when storing the options array in a local
// variable. If the options array is passed directly to `checkProps`,
// this isn't needed.
function asOptions<O extends string>(options: Option<O>[]) {
return options;
}
const options = asOptions([
{ name: 'Option1', value: 'option1' },
{ name: 'Option2', value: 'option2' },
]);
// We need to use two type parameters to detect errors. If we use just
// `O`, then TypeScript will try to be helpful and infer `O` to be the
// union of the options and the value.
function checkProps<O extends string, O1 extends O>(
props: { options: Option<O>[], value?: O1 }) {
return props;
}
let myProps1 = checkProps({
options: options,
value: "option1" // OK
});
let myProps2 = checkProps({
options: options,
value: "option3" // Error
});
let myProps3 = checkProps({
options: [
{ name: 'Option1', value: 'option1' },
{ name: 'Option2', value: 'option2' },
],
value: "option3" // Error
});