如何避免TypeScript函数签名中普通对象类型重复,优化智能提示可读性?
如何避免TypeScript函数签名中普通对象类型重复,优化智能提示可读性?
嘿,我完全懂你遇到的这个问题——TypeScript把对象字面量直接展开在函数签名里的时候,确实乱糟糟的,完全不直观。下面给你几个实用的方案,既能减少冗余代码,又能让智能提示变得清爽:
第一步:用内置类型简化返回类型显示
首先你会发现,你自定义的QueryResponse其实和TypeScript内置的Pick类型功能完全一致!Pick<S, keyof O>就是从S里取出O包含的所有键对应的类型,和你写的映射逻辑一模一样。把它替换掉之后,返回类型的显示会立刻简洁很多,不会再展开一大串重复的字段。
修改后的代码:
// 删掉原来的QueryResponse,直接用内置Pick类型 function makeQuery<S extends Schema>() { return function query<O extends object>(q: O): Pick<S, keyof O> { return {} as Pick<S, keyof O>; } } interface Schema { post: { title: string; content: string } author: { name: string; bio: string } } const query = makeQuery<Schema>();
第二步:用satisfies + typeof 一键生成命名类型
TypeScript 4.9+推出的satisfies关键字简直是解决这个问题的神器!它既能让查询对象符合Schema结构(有自动补全和类型检查),又不用重复写类型定义。用户只需要写一次查询对象,就能快速得到命名类型:
// 先定义一个辅助类型,约束查询的结构(可选,但能提升补全体验) type QueryFor<S extends Schema> = Partial<{ [K in keyof S]: {} }>; // 用户使用时,只需要写一次对象 const postAuthorQuery = { post: {}, author: {} } satisfies QueryFor<Schema>; // 自动生成命名类型 type PostAuthorQuery = typeof postAuthorQuery; // 再传入query函数,智能提示就会显示PostAuthorQuery了 const res = query(postAuthorQuery);
现在你 hover 到res = query上,看到的函数签名会变成:
const query: <PostAuthorQuery>(q: PostAuthorQuery) => Pick<Schema, keyof PostAuthorQuery>
第三步:如果用户偏爱直接传字面量,显式指定泛型类型
如果用户不想额外定义变量,也可以让他们先写类型别名,再用satisfies约束传入的对象,这样泛型会自动关联到命名类型:
type PostAuthorQuery = { post: {}, author: {} }; const res = query({ post: {}, author: {} } satisfies PostAuthorQuery);
这样智能提示里的函数签名同样会显示PostAuthorQuery,而不是展开的冗长字面量。
额外小技巧:优化makeQuery的泛型约束
把query函数的泛型约束从object改成我们定义的QueryFor<S>,能让用户在写查询对象时获得更精准的自动补全,同时智能提示里的约束也更清晰:
function makeQuery<S extends Schema>() { return function query<O extends QueryFor<S>>(q: O): Pick<S, keyof O> { return {} as Pick<S, keyof O>; } }
备注:内容来源于stack exchange,提问作者Stepan Parunashvili
相关产品推荐
相关产品推荐

