繁体   English   中英

如何使用可选参数使 TypeScript 中的 function 过载?

[英]How to overload function in TypeScript with optional parameters?

我有以下代码部分转换为 TypeScript (来自 JavaScript)。

基本上,如果存在callback参数,我总是希望 function 本身返回void 否则,返回类型Promise<object> 在此之前有一个可选参数( settings )(因此从技术上讲, callback参数可以作为settings参数传入,function 的前几行处理该用例)。

出于向后兼容的目的(并保持代码干燥),我不想创建另一个名为savePromisesaveCallback并将其分离出来。 我试图弄清楚如何让 TypeScript 足够聪明,以某种方式理解这个逻辑。

type CallbackType<T, E> = (response: T | null, error?: E) => void;

class User {
    save(data: string, settings?: object, callback?: CallbackType<object, string>): Promise<object> | void {
        if (typeof settings === "function") {
            callback = settings;
            settings = undefined;
        }

        if (callback) {
            setTimeout(() => {
                callback({"id": 1, "settings": settings});
            }, 1000);
        } else {
            return new Promise((resolve) => {
                setTimeout(() => {
                    resolve({"id": 1, "settings": settings});
                }, 1000);
            });
        }
    }
}

const a = new User().save("Hello World"); // Should be type Promise<object>, should eventually resolve to {"id": 1, "settings": undefined}
const b = new User().save("Hello World", (obj) => {
    console.log(obj); // {"id": 1, "settings": undefined}
}); // Should be type void
const c = new User().save("Hello World", {"log": true}); // Should be type Promise<object>, should eventually resolve to {"id": 1, "settings": {"log": true}}
const d = new User().save("Hello World", {"log": true}, (obj) => {
    console.log(obj); // {"id": 1, "settings": {"log": true}}
}); // Should be type void

我很确定我想要的类型文件将类似于以下内容。 不确定我在这里是否准确。

save(data: string, settings?: object): Promise<object>;
save(data: string, callback: CallbackType<object, string>): void;
save(data: string, settings: object, callback: CallbackType<object, string>): void;

似乎可以通过执行以下操作来处理作为settings参数用例传入的callback参数:

save(data: string, settings?: object | CallbackType<object, string>, callback?: CallbackType<object, string>): Promise<object> | void

但这太混乱了,根据我的经验,TypeScript 似乎不够聪明,无法意识到在 ZC1C425268E68A385D1AB5074FC17 中的前 4 行代码之后settings将始终是可选的 object 这意味着在调用callback时,您必须输入强制类型转换,这再次让人感觉非常混乱。

如何使用 TypeScript 实现这一目标?

TL;博士

这是解决方案(进行了一些重构):

type CallbackType<T, E> = (response: T | null, error?: E) => void;
interface ISettings {
  log?: boolean;
}
interface ISaveResult {
  id: number;
  settings: ISettings | undefined;
}

class User {
  save(data: string): Promise<ISaveResult>;
  save(data: string, settings: ISettings): Promise<ISaveResult>;
  save(data: string, callback: CallbackType<ISaveResult, string>): void;
  save(data: string, settings: ISettings, callback: CallbackType<ISaveResult, string>): void;
  save(data: string, settings?: ISettings | CallbackType<ISaveResult, string>, callback?: CallbackType<ISaveResult, string>): Promise<ISaveResult> | void {
    if (typeof settings !== "object" && typeof settings !== "undefined") {
      callback = settings;
      settings = undefined;
    }

    const localSettings = settings; // required for closure compatibility
    if (callback) {
      const localCallback = callback; // required for closure compatibility
      setTimeout(() => {
        localCallback({ id: 1, "settings": localSettings });
      }, 1000);
    } else {
      return new Promise((resolve) => {
        setTimeout(() => {
          resolve({ id: 1, "settings": localSettings });
        }, 1000);
      });
    }
  }
}

const a = new User().save("Hello World"); // User.save(data: string): Promise<ISaveResult>

const b = new User().save("Hello World", obj => { 
  console.log(obj); // obj: ISaveResult | null
}); // User.save(data: string, callback: CallbackType<ISaveResult, string>): void

const c = new User().save("Hello World", { "log": true }); // User.save(data: string, settings: ISettings): Promise<ISaveResult>

const d = new User().save("Hello World", { "log": true }, (obj) => {
  console.log(obj); // obj: ISaveResult | null
}); // User.save(data: string, settings: ISettings, callback: CallbackType<ISaveResult, string>): void

码盘

解释

Function也是Object ,因此 TypeScript 无法隐式区分两者。 通过创建特定的ISettings接口,您允许 TypeScript 区分设置 object 和回调 function。

最简单的查看方法是查看 TypeScript 输出的错误以及代码流进行时的变量类型,例如( 您的代码):

  • if条件下将鼠标悬停在settings上时:

    在此处输入图像描述

  • 将鼠标悬停在if块内的settings上时:

    在此处输入图像描述

  • callback分配错误:

    类型“Function”不可分配给类型“CallbackType”。 类型“函数”不匹配签名“(响应:object | null,错误?:字符串|未定义):无效”。(2322)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM