无需显式定义类型T,如何将Partial<T>或Partial<T>[]转换为T或T[]?
解决方案
可以通过泛型类型守卫函数实现自动类型推断,无需显式定义或重复拼写原类型结构,同时兼顾编译时类型安全和运行时数据校验。
1. 通用类型守卫函数(适配Angular Form场景)
针对Angular FormArray<FormGroup<...>>.value的特性(所有字段都会存在,仅值可能为undefined),定义以下类型守卫:
function isComplete<T>(obj: Partial<T>): obj is T { return Object.values(obj).every(val => val !== undefined); }
使用方式
直接用该函数过滤数组,TypeScript会自动推断过滤后数组的类型为原非Partial类型:
// 示例:模拟FormArray的value const partialArray: Partial<{ foo: string; bar: string; baz: string; buz: string }>[] = [ { foo: "foo1", bar: "bar1", baz: "baz1", buz: "buz1" }, { foo: "foo2", bar: undefined, baz: "baz2", buz: "buz2" }, { foo: "foo3", bar: "bar3", baz: "baz3", buz: "buz3" } ]; // filteredArray 类型自动推断为 { foo: string; bar: string; baz: string; buz: string }[] const filteredArray = partialArray.filter(isComplete);
2. 严格场景的类型守卫(处理可能缺失字段的情况)
如果你的Partial<T>数组可能存在缺失字段的对象,可以调整守卫函数,传入必填字段列表(无需显式定义类型T,TS会自动推断):
function isComplete<T>(obj: Partial<T>, requiredKeys: Array<keyof T>): obj is T { return requiredKeys.every(key => obj[key] !== undefined); } // 使用示例 const filteredArray = partialArray.filter(obj => isComplete(obj, ["foo", "bar", "baz", "buz"]));
3. 替代方案:条件类型+类型断言
若不想定义守卫函数,可以复用一个条件类型来提取原类型,再配合类型断言:
// 定义一次即可复用 type ExtractComplete<T> = T extends Partial<infer U> ? U : never; // 过滤并断言类型 const filteredArray = partialArray.filter( obj => Object.values(obj).every(val => val !== undefined) ) as ExtractComplete<typeof partialArray[0]>[];
说明
- Angular Form场景下,
FormGroup.value会包含所有控件对应的字段,仅值可能为undefined,因此第一种守卫函数的运行时检查足够可靠。 - 类型守卫相比类型断言更安全,因为它同时提供运行时校验,避免无效数据进入后续逻辑。
内容的提问来源于stack exchange,提问作者Colin Emonds
相关产品推荐
相关产品推荐

