我想使用React和TypeScript定义一个包含一对事件处理程序名称和事件处理程序的对象,这样我就可以传递一个对象数组,如
{
eventHandlerName: 'onBlur',
eventHandler: (e: React.FocusEvent<HTMLInputElement>) => { /* something */},
}
我尝试将此类型定义为
type SpecifiedEventHandler<I, E extends keyof React.DOMAttributes<I>> = {
eventHandlerName: E,
handlerFunction: React.DOMAttributes<I>[E];
};
以便称之为
const myObject: SpecifiedEventHandler<HTMLInputElement, keyof React.DOMAttributes<HTMLInputElement>>[] = {
[
{
eventHandlerName: 'onBlur',
handlerFunction: (e: React.FocusEvent<HTMLInputElement>) => { /* something */},
},
/* more here */
]
};
但问题是这不够严格。我可以将'foobar'
作为handlerFunction
传递,它编译得很好。
我在这里缺少什么?关键是我希望handlerFunction
具有React.DOMAttributes<HTMLInputElement>
中与eventHandlerName
名称对应的字段类型。
谢谢!
答案 0 :(得分:1)
问题是数组元素的类型是SpecifiedEventHandler<HTMLInputElement, keyof React.DOMAttributes<HTMLInputElement>>
,意味着E
将是keyof React.DOMAttributes<HTMLInputElement>>
所以handlerFunction
将是React.DOMAttributes<HTMLInputElement>[keyof React.DOMAttributes<HTMLInputElement>>]
所以基本上 ANY 值,可以是React.DOMAttributes<HTMLInputElement>
属性的值,包含{}
等很多类型,因此任何类型都与handlerFunction
兼容。
如果为E
指定更具限制性的类型,则会得到所需的错误,但可能不是具有多个事件类型数组的所需功能:
const myObject: SpecifiedEventHandler<HTMLInputElement, 'onBlur'>[] =
[
{
eventHandlerName: 'onBlur',
handlerFunction: '(e: React.FocusEvent<HTMLInputElement>) => { /* something */},'
},
]; // Error
const myObjectOk: SpecifiedEventHandler<HTMLInputElement, 'onBlur'>[] =
[
{
eventHandlerName: 'onBlur',
handlerFunction: (e: React.FocusEvent<HTMLInputElement>) => { /* something */},
},
]; // Ok
您可以创建一个辅助函数来验证数组中的每个条目,您需要为每个项目手动调用它:
function event<I, E extends keyof React.DOMAttributes<I>>(event: SpecifiedEventHandler<I, E>) : typeof event {
return event;
}
const myObject: SpecifiedEventHandler<HTMLInputElement, keyof React.DOMAttributes<HTMLInputElement>>[] =
[
// Fun trick I is inferred based on return type
event({
eventHandlerName: "onBlur",
handlerFunction: (e: React.FocusEvent<HTMLInputElement>) => { /* something */},
}),
// Error eventHandlerName not ok
event({
eventHandlerName: "onBlur2",
handlerFunction: (e: React.FocusEvent<HTMLInputElement>) => { /* something */},
}),
// Error handlerFunction not ok
event({
eventHandlerName: "onBlur",
handlerFunction: '(e: React.FocusEvent<HTMLInputElement>) => { /* something */}',
}),
];