TypeScript如何让unWrap函数返回推导后类型而非类型表达式?
问题描述
我在编写TypeScript代码时实现了一个unWrap()函数,用于将带有嵌套Ref类型的属性转换为对应原始类型。代码如下:
interface Ref<T = any> { value: T; } type UnwrapRef<T extends object> = { [K in keyof T]: T[K] extends Ref<infer V> ? V : T[K]; }; function wrap<T extends unknown>(val: T): Ref<T> { return { value: val, }; } function unWrap<T extends object>(val: T) { for (let key in val) { if ((val[key] as any).value !== undefined) { val[key] = (val[key] as any).value; } } return val as UnwrapRef<T>; } // 这里type_test能正确展开为明确类型 type type_test = UnwrapRef<{ foo: number; bar: Ref<{ baz: number; }>; }>; // 但res的类型提示还是UnwrapRef<原始类型表达式>,而非展开后的明确类型 const res = unWrap({ foo: 1, bar: wrap({ baz: 10, }), });
基础逻辑运行正常,UnwrapRef能正确推导出type_test的最终展开类型,但变量res的类型提示仍为原始的类型表达式,而非像type_test那样的展开后的明确结果,尽管自动补全功能正常。想知道有没有办法让res的类型提示更简洁美观?
解决方案
要让TypeScript在类型提示中展开UnwrapRef的结果,可以通过以下方式实现:
1. 新增Prettify工具类型强制展开嵌套类型
定义一个专门用于触发类型展开的工具类型,让TypeScript显示扁平化的最终类型结构:
type Prettify<T> = { [K in keyof T]: T[K]; } & {};
修改UnwrapRef的定义,用Prettify包裹结果:
type UnwrapRef<T extends object> = Prettify<{ [K in keyof T]: T[K] extends Ref<infer V> ? V : T[K]; }>;
此时res的类型提示会自动展开为:
const res: { foo: number; bar: { baz: number; }; }
2. 直接在unWrap函数返回时处理类型
如果不想修改UnwrapRef,也可以在函数返回时用Prettify处理返回类型:
function unWrap<T extends object>(val: T) { for (let key in val) { if ((val[key] as any).value !== undefined) { val[key] = (val[key] as any).value; } } return val as Prettify<UnwrapRef<T>>; }
原理说明
TypeScript默认会保留类型别名、映射类型的原始表达式,而Prettify通过重新映射属性并交叉空对象,触发TypeScript的类型展开逻辑,从而在编辑器提示中显示扁平化的最终类型。
内容的提问来源于stack exchange,提问作者Aiysosis
相关产品推荐
相关产品推荐

