[英]How to set type for event.target.value?
I have this Select component:我有这个 Select 组件:
type SelectProps = {
title: string;
name: string;
items: string[];
onChange: (e: ChangeEvent<HTMLSelectElement>) => void;
defValue: string;
};
const Select: FC<SelectProps> = ({ title, name, items, onChange, defValue }) => {
return (
<>
<label htmlFor={name}>
{title}:
</label>
<select name={name} onChange={onChange} defaultValue={defValue}>
{items.map((item) => (
<option value={item} key={item}>
{item}
</option>
))}
</select>
</>
);
};
and I'm handling onChange with this function:我正在用这个 function 处理 onChange:
const onThemeChange = (e: ChangeEvent<HTMLSelectElement>) => {
const theme = e.target.value;
setTheme(theme)
};
...
<Select
title='Theme'
defValue={props.theme}
name='theme'
items={['light', 'dark']}
onChange={onThemeChange}
/>
My setTheme
action creator accepts argument with type 'light' | 'dark'
我的
setTheme
动作创建者接受类型为'light' | 'dark'
'light' | 'dark'
, so I'm getting an error: 'light' | 'dark'
,所以我收到一个错误:
Argument of type 'string' is not assignable to parameter of type '"light" | "dark"'
What is the best way to solve this issue?解决此问题的最佳方法是什么?
There is away, but it requires a little trick.有距离,但它需要一个小技巧。
First, let's recognize the relationships between types in your SelectProps
:首先,让我们认识一下
SelectProps
中类型之间的关系:
items
are string literalsitems
是字符串文字onChange
, the event will have a target.value
equal to one of your items
onChange
中,该事件的target.value
等于您的items
之一defValue
should also be one of the items
defValue
也应该是其中items
To express these constraints, we need to use a generic interface.为了表达这些约束,我们需要使用通用接口。
type SelectProps<T extends string> = {
title: string;
name: string;
items: T[];
onChange: (e: ChangeEvent<HTMLSelectElement> & { target: { value: T }}) => void;
defValue: DeferTypeInference<T>;
};
const Select = function<T extends string>({ title, name, items, onChange, defValue }: SelectProps<T>) {
return (
<>
<label htmlFor={name}>
{title}:
</label>
<select name={name} onChange={onChange} defaultValue={defValue}>
{items.map((item) => (
<option value={item} key={item}>
{item}
</option>
))}
</select>
</>
);
};
We have achieved everything.我们已经取得了一切。
<Select
title='Theme'
defValue="light" // only "light" or "dark" are accepted
name='theme'
items={['light', 'dark']}
onChange={event => event.target.value} // event.target.value is "light" or "dark"
/>
Note the use of a type called DeferTypeInference<T>
.请注意使用名为
DeferTypeInference<T>
的类型。 If you're curious why it's there, check out this answer .如果您好奇它为什么会出现,请查看此答案。
The quickest way of doing so would be to do type assertions.最快的方法是进行类型断言。
Assuming that this is how you initialised the state,假设这是您初始化 state 的方式,
type ThemeState = 'light' | 'dark';
const [theme, useTheme] = useState<ThemeState>('light');
And then, on your onThemeChange
method, you will assert the value
as ThemeState
然后,在您的
onThemeChange
方法上,您将value
断言为ThemeState
const theme = e.target.value as ThemeState;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.