类型化约束的 TypeScript 推理



我有一些描述 API 调用的类型。举个例子:

export class RequestType {
prop1: string;
prop2: string;
}
export class ResponseType {
prop3: string;
prop4: string;
}

每个请求类型都链接到响应类型。我目前正在做的是定义一个接口IReturn<T>并将其添加到请求类型中:

export interface IReturn<T> {}
export class RequestType implements IReturn<ResponseType> {
prop1: string;
prop2: string;
}

然后我有一个服务,我想有一个方法从请求类型的构造函数推断请求和响应类型:

import { RequestType, IReturn } from './dto';
export class SomeService {
callApi<TRequest extends IReturn<TResponse>, TResponse>(dto: Request) TResponse {
// implementation
}
}

但是,当我尝试调用该服务时,TypeScript 可以正确推断TRequest,但TResponse绑定到{}

// response is a {} and not a ResponseType!!
const response = this.someService.call(requestInstance);

我现在有点不知所措。如何重构服务、接口或 dtos 以便对请求和响应类型进行类型推断?

这里有几个问题,第一个是你有未使用的泛型参数,因为打字稿使用结构类型系统,这些几乎被忽略了。您可以在此常见问题解答中看到此记录。第二个问题是打字稿不会做类型推断来猜测TResponse什么时候TRequest extends IReturn<TResponse>它只会选择最简单的TResponse通常是{}

为了绕过这些限制,我们可以首先在IReturn<T>中使用 type 参数 ,例如我们可以有一个表示T构造函数的字段(但实际上任何用法都可以,即使是虚拟的也说_unusedField: T(。对于第二个问题,我们可以使用条件类型从IReturn<T>中提取T

export class ResponseType {
prop3: string;
prop4: string;
}
export interface IReturn<T> { returnCtor : new (...args: any[] ) => T; }
export class RequestType implements IReturn<ResponseType> {
returnCtor = ResponseType;
prop1!: string;
prop2!: string;
}
export class SomeService {
callApi<TRequest extends IReturn<any>>(dto: TRequest) : TRequest extends IReturn<infer U> ? U : never {
return null as any
}
}
const someService = new SomeService;
const requestInstance = new RequestType;
const response = someService.callApi(requestInstance);

游乐场链接

最新更新