TypeScript中如何类型安全初始化未知泛型类型的字段?
AoS与SoA类型安全转换的TypeScript实现方案
你的核心问题是初始化SoA<Type>对象时,空对象{}不符合类型要求——因为SoA<Type>要求每个键都对应一个数组类型。下面提供两种类型安全的解决思路:
方法一:Partial类型过渡 + 动态初始化数组
利用Partial<SoA<T>>允许对象暂时缺少属性,遍历过程中为每个键初始化空数组,最后断言为完整的SoA<T>类型:
type SoA<T> = { [K in keyof T]: T[K][] }; type AoS<T> = T[]; // 简化定义,AoS本质就是目标结构体的数组 function aos2soa<T>(aos: AoS<T>): SoA<T> { const soa: Partial<SoA<T>> = {}; for (const struct of aos) { for (const key in struct) { // 若当前键的数组未初始化,先创建空数组 if (!soa[key]) { soa[key] = []; } // 非空断言确保类型安全(此时数组已存在) soa[key]!.push(struct[key]); } } // 断言为完整类型,此时所有键都已初始化数组 return soa as SoA<T>; }
方法二:提前初始化所有键的数组(更严谨)
先从输入数组中提取所有键,提前为每个键创建空数组,避免非空断言:
type SoA<T> = { [K in keyof T]: T[K][] }; type AoS<T> = T[]; function aos2soa<T>(aos: AoS<T>): SoA<T> { // 处理空数组场景,直接返回各键对应空数组的对象 if (aos.length === 0) { return {} as SoA<T>; } // 提取第一个结构体的所有键,并断言为T的键类型 const keys = Object.keys(aos[0]) as (keyof T)[]; // 初始化每个键的空数组 const soa = keys.reduce((acc, key) => { acc[key] = []; return acc; }, {} as SoA<T>); // 遍历填充数据 for (const struct of aos) { for (const key of keys) { soa[key].push(struct[key]); } } return soa; }
说明
- 两种方法都保持了类型安全,不会丢失
Type的类型信息; - 方法一无需依赖输入数组的非空性,兼容性更强;
- 方法二通过提前初始化数组,避免了非空断言,代码更严谨。
内容的提问来源于stack exchange,提问作者Miguel Bartelsman
相关产品推荐
相关产品推荐

