javascript - 如何在 TypeScript 中定义由事件处理程序名称和事件处理程序组成的类型

标签 javascript reactjs typescript

我想使用 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 .

谢谢!

最佳答案

问题是数组元素的类型是SpecifiedEventHandler<HTMLInputElement, keyof React.DOMAttributes<HTMLInputElement>>这意味着E将是keyof React.DOMAttributes<HTMLInputElement>>所以handlerFunction将是React.DOMAttributes<HTMLInputElement>[keyof React.DOMAttributes<HTMLInputElement>>]所以基本上任何值都可以是 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 */}',
        }),
    ];

关于javascript - 如何在 TypeScript 中定义由事件处理程序名称和事件处理程序组成的类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50228278/

相关文章:

reactjs - 我如何循环 React bootstrap 轮播项目

javascript - Chrome 的 JavaScript 控制台在评估对象方面是否懒惰?

javascript - 谷歌地图 : Overlay point not showing up

javascript - Style.visibility 不隐藏元素

javascript - 如何将所有socket.io分离到不同的文件

Typescript:在这种情况下如何使用泛型类型输入函数?

javascript - 如何使用 Html anchor <a> 发送 AJAX Post 请求

javascript - React Redux 无法与 Next.js 和 NodeJS 一起正常工作

angularjs - 如何在一个项目中结合 Angular 和 React

reactjs - 使用 Material UI makeStyles 时输入的 props