假设我有一个采用通用类的抽象类
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
是 all 异步的。
我可以使用TypeScript静态地执行此操作吗?
也许正在使用Extract<keyof IUserService, Function>
?然后将其传递给某些东西?
也就是说,如果您尝试extend RegisterableClass
并将其传递给泛型,而不是所有函数都异步,则打字稿将无法编译
答案 0 :(得分:3)
如果我正确理解,您希望constrain the type parameter传递给RegisterableClass
的方法都是异步的(意味着它们返回promise)。
如果是这样,您可以这样实现:
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
}
如果AllMethodsAreAsync<I>
是对象类型,其函数值属性返回promise,则类型函数I
将等效于I
。但是,如果I
具有任何不返回诺言的函数值属性,则AllMethodsAreAsync<I>
的相应属性将被更改为改为返回诺言。
然后,如果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>'.
那是您想要的吗?希望能有所帮助;祝你好运!