[英]Typescript: function with argument of enum type assigned to callback with argument type of string
I have a dropdown component with a callback onSelect:(option: string) => void
我有一个带有回调
onSelect:(option: string) => void
的下拉组件
I'm using it as a sort picker in one application, where the options are of enum type:我在一个应用程序中将它用作排序选择器,其中选项是枚举类型:
enum SORT_OPTIONS {
LATEST = 'LATEST',
OLDEST = 'OLDEST'
}
const onSortSelect = (val: SORT_OPTIONS) => {...}
<MyDropdown onSelect={onSortSelect} ... />
And typescript complains: typescript 抱怨:
Type '(val: SORT_OPTIONS) => void' is not assignable to type '(option: string) => void'.
Types of parameters 'val' and 'option' are incompatible.
Type 'string' is not assignable to type 'SORT_OPTIONS'. TS2322
It's a bit counter-intuitive but makes sense, since in MyDropdown
a string option
will be passed to the onSortSelect
callback, which requires an enum value.这有点违反直觉,但很有意义,因为在
MyDropdown
中,一个字符串option
将传递给onSortSelect
回调,这需要一个枚举值。
Question is what is the best way to fix the types here?问题是在这里修复类型的最佳方法是什么? IMO both functions are typed correctly,
onSelect
should accept any string since MyDropdown
can be used in any context. IMO 两个函数都输入正确,
onSelect
应该接受任何字符串,因为MyDropdown
可以在任何上下文中使用。 onSortSelect
should only accept SORT_OPTIONS
. onSortSelect
应该只接受SORT_OPTIONS
。
Currently I'm casting the type of onSortSelect: <MyDropdown onSelect={onSortSelect as (val:string) => void}... />
but it feels quite verbose目前我正在投射 onSortSelect 的类型:
<MyDropdown onSelect={onSortSelect as (val:string) => void}... />
但感觉很冗长
Your callback deals with onSelect:(option: string) => void
您的回调处理
onSelect:(option: string) => void
This means that it passes any string to the handle, like: hello
, test
, and so on.这意味着它将任何字符串传递给句柄,例如:
hello
、 test
等。
But your const onSortSelect = (val: SORT_OPTIONS) => {...}
expects only subset of strings: LATEST, OLDEST.但是您的
const onSortSelect = (val: SORT_OPTIONS) => {...}
只需要字符串的子集:LATEST、OLDEST。
So, TypeScript warns you that you can't pass the whole set to a function that expects subset.因此,TypeScript 警告您不能将整个集合传递给期望子集的 function。
To fix the issue, you need to update your onSelect
handler to:要解决此问题,您需要将
onSelect
处理程序更新为:
onSelect:(option: SORT_OPTIONS) => void
I managed to fix the types with Generics, no typescript error我设法用 Generics 修复了类型,没有 typescript 错误
enum SORT_OPTIONS {
NEWEST='1',
OLDEST='2'
}
interface DropdownProps<T extends string> {
onSelect: (val: T) => void;
options: T[];
}
const Dropdown = <T extends string>(props: DropdownProps<T> & {children?: React.ReactNode}) =>{
const {onSelect, options} = props;
return <select onChange={(evt) => onSelect(evt.target.value as T)}>
{options.map(option => <option>{option}</option>)}
</select>
};
const TestComp:React.FC = () => {
const onSelect = (val: SORT_OPTIONS) => {
switch (val) {
case SORT_OPTIONS.OLDEST:
console.log('old');
break;
case SORT_OPTIONS.NEWEST:
console.log('new');
break;
}
};
const onSelect2 = (val: string) => {
console.log(val);
};
return <>
<Dropdown
options={[SORT_OPTIONS.NEWEST, SORT_OPTIONS.OLDEST]}
onSelect={onSelect}
/>
<Dropdown
options={['aaa', 'bbb']}
onSelect={onSelect2}
/>
</>
};
Note that注意
Dropdown
with the regular React.FC
, see the discussion here: How to use generics in props in React in a functional component?React.FC
键入Dropdown
,请参阅此处的讨论: 如何在功能组件中的 React 中的道具中使用 generics? Please comment if you find a different conclusion from the link.如果您从链接中发现不同的结论,请发表评论。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.