我正在构建一个通用查询库。它可以采用“架构”,并可以根据您查询的内容返回映射的输出类型。
一个简化的示例如下所示:
type QueryResponse<S extends object, O extends object> = {
[K in keyof O]: K extends keyof S
? S[K]
: never
}
function makeQuery<S extends Schema>() {
return function query<O extends object>(q: O): QueryResponse<S, O> {
return {} as QueryResponse<S, O>
}
}
interface Schema {
post: { title: string; content: string }
author: { title: string; content: string }
}
const query = makeQuery<Schema>();
// <-- hover over here
const res = query({ post: {}, author: {} })
res.post.title // types as a string
res.author.title // types as a string
如果将鼠标悬停在
res = query
上,智能感知可能会开始显得难以理解:
const query: <{
post: {};
author: {};
}>(q: {
post: {};
author: {};
}) => QueryResponse<Schema, {
post: {};
author: {};
}>
如果
query
的智能感知更具可读性,我会喜欢它。
也许用户可以提供类型名称,例如:
const query: <PostAuthorQuery>(q: PostAuthorQuery) => QueryResponse<Schema, PostAuthorQuery>
据我所知,用户没有从对象创建
PostAuthorQuery
的惯用方法。到目前为止,我知道他们可以做到这一点:
const _query = { post: {}, author: {} };
type _PostAuthorQuery = typeof _query;
interface PostAuthorQuery extends _PostAuthorQuery {};
const query: PostAuthorQuery = _query;
但我真的不能要求他们为每个查询编写这个样板。
我是否可以为用户创建一些帮助程序,以便当他们生成查询并使用我的
query
函数时,他们会看到更简洁的智能感知定义?
或者也许我可以用不同的方式处理这个问题?也许如果我使用不同的输入(即不是对象),智能感知会看起来更好?我尝试了构建器模式,但智能感知看起来不太好。
正如评论中所讨论的,解决这个问题的唯一方法是 a) 显式定义类型:
type PostAuthorQuery: { post: {}, object: { } }
const query: PostAuthorQuery = { post: { }, object: { } }
或者,为了避免两次写入同一个对象,您可以使用接口技巧:
const _query = { post: {}, author: {} };
type _PostAuthorQuery = typeof _query;
interface PostAuthorQuery extends _PostAuthorQuery {};
const query: PostAuthorQuery = _query;