TypeScript:在函数中强制使用通用推断的类型参数

时间:2019-02-18 19:46:32

标签: typescript generics

是否有一种方法可以限制下面的run调用,使其严格限制为RequestType<>指定的类型参数所允许的类型?返回类型R似乎有效,但是RQ并不严格。

class RequestType<RQ, R> {
    constructor(public readonly method: string) { }
 }

interface FooRequest {
    foo: string;
    bar: string;
}

interface FooResponse {
    foobar: string;
}

const FooRequestType = new RequestType<FooRequest, FooResponse>("foo");

function run<RQ, R>(type: RequestType<RQ, R>, request: RQ): R {
    // real code here
    return {} as R;
}

这是电话

const foo1 = run(FooRequestType, {}); // want an error here
const foo2 = run(FooRequestType, {
    foo: "foo" // want an error here
});
const foo3 = run(FooRequestType, {
    foo: "foo",
    bar: "bar",
    baz: "" // error here -- good
});

这里是TypeScript playgound的链接。感谢您的帮助-谢谢!

1 个答案:

答案 0 :(得分:1)

来自docs由于TypeScript是结构类型系统,所以类型参数仅在作为成员类型的一部分使用时才影响结果类型。

在您的情况下,RequestType<{},FooResponse>RequestType<FooRequest, FooResponse>具有完全相同的结构,因此顺应

run(FooRequestType, {});

类型正确推断为

run<{},FooResponse>(FooRequestType: RequestType<{}, FooResponse>, {}: {})


一种解决方法是在RequestType中添加一些(如果需要的话是伪造的)属性,以使RequestType<RQ1,R>RequestType<RQ2,R>不同。该属性可能是

class RequestType<RQ, R> {
    private readonly acc: (req: RQ) => RQ | undefined;
    constructor(public readonly method: string) { }
}

请注意,要使此特定解决方案成功,您需要启用strictFunctionTypes选项。否则,(req: FooRequest) => FooRequest将可分配给(req: {}) => {},因此FooRequestType仍将可分配给RequestType<{}, FooResponse>。您可以详细了解here


另一种方法是不允许TypeScript为request推断错误的类型,而是使其为requestType推断类型(出于可读性而从type更改):< / p>

type RequestOf<RT> = RT extends RequestType<infer RQ, any> ? RQ : never;
type ResponseOf<RT> = RT extends RequestType<any, infer R> ? R : never;
function run<RT extends RequestType<any, any>>(
    requestType: RT,
    request: RequestOf<RT>
): ResponseOf<RT> {
    return {} as ResponseOf<RT>;
}

现在,TypeScript将正确地“猜测” RTRequestType<FooRequest, FooResponse>。然后,

type RequestOf<RT> = RT extends RequestType<infer RQ, any> ? RQ : never;

基本上说:如果RTRequestType<RQ, something>,则使RequestOf<RT>等于RQ。有关infer魔术的更多信息,请参见Type inference in conditional types