有没有一种方法可以限制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玩具的链接。任何帮助表示赞赏-谢谢!
来自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
option。否则,(req: FooRequest) => FooRequest
将可分配给(req: {}) => {}
,因此FooRequestType
仍将可分配给RequestType<{}, FooResponse>
。您可以在此处了解更多信息。
一种不同的方法是不允许TypeScript为推断错误的类型request
,而是使其推断为的类型requestType
(type
出于可读性而更改):
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将正确地“猜测”RT
为RequestType<FooRequest, FooResponse>
。然后,
type RequestOf<RT> = RT extends RequestType<infer RQ, any> ? RQ : never;
基本上说:如果RT
是RequestType<RQ, something>
,则RequestOf<RT>
等于RQ
。有关该infer
魔术的更多信息,请参见条件类型中的类型推断。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句