typescript - 将输入参数约束为某个泛型类型的超类型,并使结果类型为同一类型
问题描述
我正在尝试制作一种类型安全的 GraphQL 数据获取方法。我使用服务器上生成的类型,并希望选择在这些类型上定义的属性子集作为结果类型。
从服务器生成的代码看起来像
export interface Dream {
id: number;
title?: string;
}
export interface IQuery {
dream(id: number): Dream | Promise<Dream>;
}
检索数据的函数:
function doQuery<
QName extends keyof IQuery,
QParams extends Parameters<IQuery[QName]>,
R extends Partial<ReturnType<IQuery[QName]>>
>(queryName: QName, params: QParams, resultSelector: R): R {
return {} as R; // stub
}
还有一个实用程序类,可以在运行时使用“类型”
class types {
static number: number;
static string: string;
static boolean: boolean;
}
例如,当调用函数时
const result = doQuery("dream", [2], {
title: types.string
});
结果类型被正确推断为
const result: {
title: string;
}
当我打电话时
const result = doQuery("dream", [2], {
nonExisting: types.string,
});
编译器会抛出Object literal may only specify known properties, and 'nonExisting' does not exist in type 'RecursivePartial<Dream>
,这就是我想要的。
但是,当使用
const result = doQuery("dream", [2], {
id: types.number,
nonExisting: types.string,
});
编译器说没关系,我不希望这样。我希望编译器以与以前相同的方式抛出。
结果类型应始终与 resultSelector 类型具有相同的类型。
在我迄今为止试验过的代码中,Dream | Promise<Dream>
尚未处理查询结果的可能性。我相信条件类型应该可以做到这一点。
Partial 部分也是我能想到的最好的部分,但实际上应该是这样,ReturnType<IQuery[QName]> extends R
而不是相反,我不知道如何在 Typescript 中表达这一点。
是否可以在当前的 Typescript 技术中实现我正在寻找的约束?如果是这样,怎么做?如果不是,为什么不呢?
提前致谢。
解决方案
我设法使它与
type Awaited<T> = T extends { then(onfulfilled: (value: infer U) => any): any }
? U
: T extends { then(...args: any[]): any }
? never
: T;
和
type Subset<S, F> = { [key in keyof S]: key extends keyof F ? F[key] : never };
和
function doQuery<
QName extends keyof IQuery,
QParams extends Parameters<IQuery[QName]>,
R extends Subset<R, Awaited<ReturnType<IQuery[QName]>>>
>(queryName: QName, params: QParams, resultSelector: R): R {
return {} as R;
}
推荐阅读
- android - 我如何编写查询以从医生集合中获取 id 然后我将此 id 转换为当前身份验证用户 id
- python - Pandas:有条件的 2 列的累积和
- c++ - 当我在将文件读取到二维 c 字符串数组后尝试计算任何内容时出现 C++ 分段错误
- php - 是否可以为不同的文件设置不同的 phpcs 配置值?
- reactjs - useTransition 与 react-spring 作为组件更改
- excel - 如何将所有单元格值存储在 VBA 中?
- c++ - handleMessage 看不到我的类和函数
- python - 如何在 iPad Pro 上运行 Python?
- javascript - 如何从名称值中收集所有数据以便我可以使用它?
- php - 在 PHP 应用程序中捆绑 React 文件?