gpt4 book ai didi

typescript - 如何使用可选参数在 TypeScript 中重载函数?

转载 作者:行者123 更新时间:2023-12-04 13:36:48 26 4
gpt4 key购买 nike

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

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

为了向后兼容(并保持代码干燥),我不想创建另一个名为 savePromise 的函数。或 saveCallback并将其分开。我试图弄清楚如何让 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;

好像是 callback参数作为 settings 传入可以通过执行以下操作来处理参数用例:
save(data: string, settings?: object | CallbackType<object, string>, callback?: CallbackType<object, string>): Promise<object> | void

但这非常困惑,根据我的经验,TypeScript 似乎不够聪明,无法意识到 settings将始终是函数中前 4 行代码之后的可选对象。这意味着在拨打 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

code pan

解释
FunctionObject同样,因此 TypeScript 无法隐式区分两者。通过创建特定 ISettings接口(interface),您允许 TypeScript 区分设置对象和回调函数。

最简单的方法是查看 TypeScript 输出的错误以及随着代码流的进展而变量的类型,例如( your code ):
  • 悬停在 settings 上时在 if健康)状况:

    enter image description here
  • 悬停在 settings 上时内if堵塞:

    enter image description here
  • callback赋值错误:

    Type 'Function' is not assignable to type 'CallbackType'. Type 'Function' provides no match for the signature '(response: object | null, error?: string | undefined): void'.(2322)

  • 关于typescript - 如何使用可选参数在 TypeScript 中重载函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61354745/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com