如何使用 React TypeScript 创建通用事件处理程序
How to create Generic event handler with React TypeScript
我有一个名为 Button
的组件,它接受 onChange
props。现在 onChange: event: React.ChangeEvent<HTMLInputElement>
的类型并且工作正常。我想创建一个 union type
期望以下两种类型。我想做这样的事情,使这个 onChange
通用类型。
import React from 'react';
type handleChange = (value: string,checked: boolean,name: string) => void
type eventHandleChange = <T extends HTMLElement>(
event: React.ChangeEvent<T>
) => void;
type Change = handleChange | eventHandleChange;
type buttonProps ={
onChange?: Change
}
export const Button =(Props:buttonProps) =>{
//code here
}
但是当我试图将一个函数传递给像这样的道具时,它给我一个错误
import React from 'react';
import Button from '../button';
export const FooComponent=()=>{
const changHandler = (event: React.ChangEvent<HTMLInputElement>)=>{
setSelectedValue(event.targe.value)
}
return (
<Button onChange={changeHandler} />
)
}
错误
'(event: React.ChangeEvent<HTMLInputElement>) => void' is not assignable to type 'eventHandleChange | handleChange | undefined'.
Type '(event: React.ChangeEvent<HTMLInputElement>) => void' is not assignable to type 'eventHandleChange'.
Types of parameters 'event' and 'event' are incompatible.
Type 'ChangeEvent<T>' is not assignable to type 'ChangeEvent<HTMLInputElement>'.
Type 'T' is not assignable to type 'HTMLInputElement'.
Type 'HTMLElement' is missing the following properties from type 'HTMLInputElement': accept, align, alt, autocomplete, and 49 more.
因为 HTMLInputElement
是从 HTMLElement
延伸而来 T
在这里应该对所有 HTMLElement
通用。我不确定我在实施过程中遗漏了什么。
在处理回调时,您可能认为的“更宽泛”和“更窄化”会颠倒过来。为了将 A 分配给 B,其中 A 和 B 都是回调,A 必须接受 B 接受的所有类型。如果 A 只接受 B 所做的特定子集,则它不能分配给 B。
在这里,您有一个类型 eventHandleChange
可以处理任何 HTMLElement
上的更改。您尝试分配给它的回调只接受 HTMLInputElement
的更改事件,因此它不可分配。
解决此问题的一种可能方法是将通用 T
移到链的更高位置,这样我们就可以说 buttonProps
可以进行非常具体的回调。
type handleChange = (value: string, checked: boolean, name: string) => void
type eventHandleChange<T extends HTMLElement> = (
event: React.ChangeEvent<T>
) => void;
type Change<T extends HTMLElement> = handleChange | eventHandleChange<T>;
type buttonProps = {
onChange?: Change<HTMLInputElement>
}
如果您需要接受任何类型的 HTML 元素的类型,您可以使用:
type AnyHTMLElement = HTMLElementTagNameMap[keyof HTMLElementTagNameMap]
如果它来自 querySelector 或 ref,您可能需要在定义中添加 | null
我有一个名为 Button
的组件,它接受 onChange
props。现在 onChange: event: React.ChangeEvent<HTMLInputElement>
的类型并且工作正常。我想创建一个 union type
期望以下两种类型。我想做这样的事情,使这个 onChange
通用类型。
import React from 'react';
type handleChange = (value: string,checked: boolean,name: string) => void
type eventHandleChange = <T extends HTMLElement>(
event: React.ChangeEvent<T>
) => void;
type Change = handleChange | eventHandleChange;
type buttonProps ={
onChange?: Change
}
export const Button =(Props:buttonProps) =>{
//code here
}
但是当我试图将一个函数传递给像这样的道具时,它给我一个错误
import React from 'react';
import Button from '../button';
export const FooComponent=()=>{
const changHandler = (event: React.ChangEvent<HTMLInputElement>)=>{
setSelectedValue(event.targe.value)
}
return (
<Button onChange={changeHandler} />
)
}
错误
'(event: React.ChangeEvent<HTMLInputElement>) => void' is not assignable to type 'eventHandleChange | handleChange | undefined'.
Type '(event: React.ChangeEvent<HTMLInputElement>) => void' is not assignable to type 'eventHandleChange'.
Types of parameters 'event' and 'event' are incompatible.
Type 'ChangeEvent<T>' is not assignable to type 'ChangeEvent<HTMLInputElement>'.
Type 'T' is not assignable to type 'HTMLInputElement'.
Type 'HTMLElement' is missing the following properties from type 'HTMLInputElement': accept, align, alt, autocomplete, and 49 more.
因为 HTMLInputElement
是从 HTMLElement
延伸而来 T
在这里应该对所有 HTMLElement
通用。我不确定我在实施过程中遗漏了什么。
在处理回调时,您可能认为的“更宽泛”和“更窄化”会颠倒过来。为了将 A 分配给 B,其中 A 和 B 都是回调,A 必须接受 B 接受的所有类型。如果 A 只接受 B 所做的特定子集,则它不能分配给 B。
在这里,您有一个类型 eventHandleChange
可以处理任何 HTMLElement
上的更改。您尝试分配给它的回调只接受 HTMLInputElement
的更改事件,因此它不可分配。
解决此问题的一种可能方法是将通用 T
移到链的更高位置,这样我们就可以说 buttonProps
可以进行非常具体的回调。
type handleChange = (value: string, checked: boolean, name: string) => void
type eventHandleChange<T extends HTMLElement> = (
event: React.ChangeEvent<T>
) => void;
type Change<T extends HTMLElement> = handleChange | eventHandleChange<T>;
type buttonProps = {
onChange?: Change<HTMLInputElement>
}
如果您需要接受任何类型的 HTML 元素的类型,您可以使用:
type AnyHTMLElement = HTMLElementTagNameMap[keyof HTMLElementTagNameMap]
如果它来自 querySelector 或 ref,您可能需要在定义中添加 | null