如何结合映射类型与泛型函数实现TypeScript类型推断?
问题解答:结合映射类型推断与泛型函数调用的Builder实现
你的需求完全可行,只需调整Builder类型中tree方法的泛型约束,让TypeScript能根据传入的树节点键名自动拼接命名空间,从而实现dataPath的自动推断,同时保留Context的全局类型推断。
修改后的实现代码
type BaseType<Context, DataPath extends string> = (ctx: { data: Context; dataPath: DataPath }) => unknown; type Join<Root extends string, Leaf extends string> = Root extends '' ? Leaf : `${Root}.${Leaf}`; type RecursiveTree<Context, Namespace extends string = ''> = { [K in string]: RecursiveTree<Context, Join<Namespace, K>> | BaseType<Context, Join<Namespace, K>>; }; type Builder<Context, Ns extends string = ''> = { // 泛型约束确保每个键K对应的值使用拼接后的命名空间 tree<T extends Record<string, RecursiveTree<Context, Join<Ns, keyof T & string>>>>(tree: T): T; leaf: { create(handler: BaseType<Context, Ns>): BaseType<Context, Ns>; }; }; // 初始化根Builder,指定全局Context类型 const builder = {} as Builder<{ foo: string }>; // 链式构建示例,自动推断dataPath和Context const defn = builder.tree({ innerLeaf: builder.leaf.create((ctx) => { // ctx.dataPath 类型自动推断为 "innerLeaf" // ctx.data.foo 类型为 string }), innerTree: builder.tree({ innerLeaf: builder.leaf.create((ctx) => { // ctx.dataPath 类型自动推断为 "innerTree.innerLeaf" }), innerInnerTree: builder.tree({ innerLeaf: builder.leaf.create((ctx) => { // ctx.dataPath 类型自动推断为 "innerTree.innerInnerTree.innerLeaf" }) }) }) });
关键调整说明
tree方法的泛型约束优化:
让tree方法接收的对象T满足:每个键K对应的值都是RecursiveTree<Context, Join<Ns, K>>。TypeScript会自动将当前命名空间Ns与键名K拼接,作为子节点的命名空间前缀,从而为后续的leaf.create提供准确的dataPath类型。保留
Context的全局推断:
根Builder初始化时指定的Context类型会通过泛型传递到所有嵌套的子Builder中,无需重复标注,确保所有leaf.create中的ctx.data都能正确推断类型。链式API的友好性:
保持了原有的链式调用风格,用户无需手动定义RecursiveTree类型,直接通过builder.tree和builder.leaf.create即可构建嵌套结构,同时获得完整的类型推断支持。
内容的提问来源于stack exchange,提问作者Inkblot
相关产品推荐
相关产品推荐

