如何防止函数签名中重复使用普通对象类型?

问题描述 投票:0回答:1

背景

我正在构建一个通用查询库。它可以采用“架构”,并可以根据您查询的内容返回映射的输出类型。

一个简化的示例如下所示:

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
函数时,他们会看到更简洁的智能感知定义?

或者也许我可以用不同的方式处理这个问题?也许如果我使用不同的输入(即不是对象),智能感知会看起来更好?我尝试了构建器模式,但智能感知看起来不太好。

typescript
1个回答
0
投票

正如评论中所讨论的,解决这个问题的唯一方法是 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;
© www.soinside.com 2019 - 2024. All rights reserved.