在我的代码中,我有一个调度函数,它接受一个参数并根据参数返回另一个函数,类似于这样的:

type Reason = 'create' | 'delete';

function dispatch(reason: Reason) {
    switch(reason) {
        case 'create':
        return createInternal;
        case 'delete':
        return deleteInternal;
    }
}

function createInternal(name: string) {
    console.log(name);
}

function deleteInternal(code: number) {
    console.log(code);
}

现在这最初有效,因为我返回的函数具有相同的签名.在添加了另一个具有不同签名的函数后,我意识到这有问题."dispatch"函数的返回类型是所有可能返回的函数的联合.

下面的用法现在不再可能,因为类型脚本无法推断返回函数的正确类型.

dispatch('create')('123'); // Argument of type 'string' is not assignable to parameter of type 'never'.
dispatch('delete')(123); // Argument of type 'number' is not assignable to parameter of type 'never'.

有没有方法可以解决这个问题,或者实现一个更好的调度功能而不会出现这个问题?

这是link to a playground.

Edit

在仿制药的帮助下,我找到了一半的解决方案.现在我可以正确调用调度函数,但调度函数内部出现了我不理解的更多错误.

Playground

type Reason = 'create' | 'delete';
type DispatchedFunction<T extends Reason> = T extends 'create' ? typeof createInternal : typeof deleteInternal;

function dispatch<R extends Reason>(reason: R): DispatchedFunction<R> {
    switch(reason) {
        case 'create':
        // Type '(name: string) => void' is not assignable to type 'DispatchedFunction<R>'.
        return createInternal;
        case 'delete':
        // Type '(code: number) => void' is not assignable to type 'DispatchedFunction<R>'.
        return deleteInternal;
    }
    return () => {} // I had to add this so the function doesn't return undefined
}

推荐答案

您可以创建一个常数查找对象并索引到该对象:

type Reason = 'create' | 'delete';

const DispatchFunctions = {
    'create': createInternal,
    'delete': deleteInternal,
} as const;

function dispatch<R extends Reason>(reason: R): typeof DispatchFunctions[R] {
    return DispatchFunctions[reason];
}

function createInternal(name: string) {
    console.log(name);
}

function deleteInternal(code: number) {
    console.log(code);
}

dispatch('create')('123');
dispatch('delete')(123);

Typescript相关问答推荐

如何在第一次加载组件时加载ref数组

类型脚本泛型最初推断然后设置

如何在排版中正确键入中间件链和控制器链

如何使用泛型类型访问对象

根据上一个参数值查找参数类型,也返回类型

material 表不渲染任何数据

如何在TypeScript中将一个元组映射(转换)到另一个元组?

使用打字Angular 中的通用数据创建状态管理

从子类构造函数推断父类泛型类型

为什么不能使用$EVENT接收字符串数组?

以Angular 自定义快捷菜单

Angular:ngx-echart 5.2.2与Angular 9集成错误:NG 8002:无法绑定到选项,因为它不是div的已知属性'

为什么我的查询钩子返回的结果与浏览器的网络选项卡中看到的结果不同?

如何从MAT-FORM-FIELD-MAT-SELECT中移除焦点?

在组件卸载时try 使用useEffect清除状态时发生冲突.react +打字

作为函数参数的联合类型的键

在类型脚本中创建显式不安全的私有类成员访问函数

使用强制转换编写打字函数的惯用方法

TS不能自己推断函数返回类型

为什么 Typescript 无法正确推断数组元素的类型?