У меня есть следующий код, который частично преобразован в TypeScript (из JavaScript).
В основном, если существует параметр callback
, я всегда хочу, чтобы сама функция возвращала void
. В противном случае тип возврата Promise<object>
. С необязательным параметром (settings
) перед этим (так что технически параметр callback
может быть передан как параметр settings
, который первые несколько строк функции обрабатывают с помощью регистра).
В целях обратной совместимости (и для сохранения кода DRY) я не хочу создавать другую функцию с именем savePromise
или saveCallback
и отделять ее. Я пытаюсь понять, как заставить TypeScript быть достаточно умным, чтобы как-то понять эту логику c.
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
вы должны набрать cast, что опять-таки кажется очень грязным.
Как мне добиться этого с помощью TypeScript?