Вот как я подхожу к этому:
Придумайте отдельные типы для каждого возможного обработчика крюка:
type SyncHookHandler = (context: MyClass<any>) => boolean;
type AsyncHookHandler = (context: MyClass<any>) => Promise<boolean>;
type HookHandler = AsyncHookHandler | SyncHookHandler;
А затем сделайте MyClass
зависимым от типа HH
HookHandler
вы используете.Тип возврата invokeHandlers
может быть условным типом , который оценивается как boolean
, если HH
равно SyncHookHandler
, и Promise<boolean>
, если HH
равно AsyncHookHandler
или AsyncHookHandler | SyncHookHandler
:
class MyClass<HH extends HookHandler> {
constructor(private handlers: Array<HH>) { }
public invokeHandlers(): Promise<boolean> extends ReturnType<HH> ?
Promise<boolean> : boolean;
public invokeHandlers(): boolean | Promise<boolean> {
const rets = this.handlers.map(h => h(this));
const firstPromise = rets.find(r => typeof r !== 'boolean');
if (firstPromise) {
return firstPromise; // ? what do you want to return here
}
// must be all booleans
const allBooleanRets = rets as boolean[];
return allBooleanRets.every(b => b); // ? what do you want to return here
}
}
Я просто сделал какую-то глупую реализацию внутри invokeHandlers()
, чтобы дать представление о том, что вы будете там делать.Теперь вы можете видеть, что ваш код ведет себя как ожидалось
const myClassSync = new MyClass([
(ctx) => true,
(ctx) => false
]);
// all handlers are sync, infer boolean
const allHandlersAreOk: boolean = myClassSync.invokeHandlers()
const myClassAsync = new MyClass([
async (ctx) => Promise.resolve(true),
async (ctx) => Promise.reject()
]);
// all handlers are async, infer Promise<boolean>
// note you do not "await" it, since you want a Promise
const allAsyncHandlersAreOk: Promise<boolean> = myClassAsync.invokeHandlers()
const myClassMix = new MyClass([
async (ctx) => Promise.resolve(true),
(ctx) => true
]);
// at least one handler is async, infer Promise<boolean>
// note you do not "await" it, since you want a Promise
const allMixedHandlersAreOk: Promise<boolean> = myClassMix.invokeHandlers()
Это работает для вас?
Обратите внимание, что, поскольку пример кода не имел структурной зависимости от универсального параметра T
,Я удалил его .Если вам это нужно, вы можете добавить его обратно в соответствующие места, но я предполагаю, что вопрос больше в том, чтобы обнаружить-синхронизировать, если вы можете, а не о каком-то универсальном типе.
Хорошо, надеюсь, это поможет;удачи!