TypeScript关于类型约束的推断

时间:2018-06-28 14:17:36

标签: typescript

我有一些描述Api呼叫的类型。例如:

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
    }
}

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

TRequest

但是,当我尝试调用该服务时,TypeScript可以正确推断TResponse,但是{}被绑定到// response is a {} and not a ResponseType!! const response = this.someService.call(requestInstance);

all

现在我有点茫然。我如何重构服务,接口或dto以便对 请求和响应类型进行类型推断?

1 个答案:

答案 0 :(得分:1)

这里有几个问题,第一个是您有未使用的泛型参数,因为打字稿使用结构化类型系统,因此这些问题几乎被忽略了。您可以在此faq中看到此文档。第二个问题是,当TResponse时,打字稿不会进行类型推断来猜测TRequest extends IReturn<TResponse>,而只会使用最简单的TResponse,通常是{}

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

Playground link