确保作为泛型传递的接口中的每个函数都是异步的



假设我有一个抽象类,它采用泛型

export abstract class RegisterableClass<InstanceType>

以及以下实施者:

class UserService extends RegisterableClass<IUserService> implements IUserService {
  someConstant: 42,
  async getAllUsers: (): User[] => {...}
}

具有如下接口:

interface IUserService {
  someConstant: number;
  getAllUsers: () => Promise<User[]>;
}

我想确保传递的泛型,IUserService ,在这种特殊情况下,都是异步的。

我可以以某种方式使用 TypeScript 静态执行此操作吗?

也许使用Extract<keyof IUserService, Function>? 然后依次传递给某物?

也就是说,如果您尝试extend RegisterableClass并传递给它一个并非所有函数都是异步的泛型,则打字稿将不会编译

如果我

理解正确,您希望将传递给RegisterableClass的类型参数限制为方法都是异步的(意味着它们返回承诺(。

如果是这样,您可以像这样实现:

type AllMethodsAreAsync<I> = {
    [K in keyof I]: I[K] extends (...args: any) => infer R ?
    R extends Promise<any> ? I[K] : (...args: any) => Promise<R> :
    I[K]
}
export abstract class RegisterableClass<I extends AllMethodsAreAsync<I>> {
    // ... something involving I, hopefully
}

如果 I 是函数值属性返回 promise 的对象类型,则类型函数AllMethodsAreAsync<I>将等效于 I。 但是,如果I具有任何不返回 promise 的函数值属性,则 AllMethodsAreAsync<I> 的相应属性将更改为返回 promise。

然后,如果I extends AllMethodsAreAsync<I>传递了通用约束,那就太好了。 否则,您应该会收到一个错误,告诉您I中的哪些内容不起作用。 喜欢这个:

// adding this so standalone example works
type User = { u: string }; 
interface IOkayService {
    someConstant: number;
    getAllUsers(): Promise<User[]>;
}
type OkayService = RegisterableClass<IOkayService>; // okay
interface IBadService {
    someConstant: number;
    getAllUsers(): Promise<User[]>;
    getSomethingSynchronously(x: string): number;
}
type BadService = RegisterableClass<IBadService>; // error!
//                                  ~~~~~~~~~~~
// Type 'IBadService' does not satisfy the constraint 'AllMethodsAreAsync<IBadService>'.
// Types of property 'getSomethingSynchronously' are incompatible.
// Type '(x: string) => number' is not assignable to type '(...args: any) => Promise<number>'.
// Type 'number' is not assignable to type 'Promise<number>'.

游乐场链接

这能做到你想要的吗? 希望有帮助;祝你好运!

最新更新