如何创建支持部分默认值的TypeScript测试数据生成函数?
解决方案:定义支持深层部分属性的测试数据参数类型
问题原因
你之前的写法出错核心原因有两个:
Omit<Partial<Locomotive>, 'engine' | 'name'>中,engine的类型是Engine | undefined(Partial仅把属性变为可选,但保留了原类型的完整性),而你重新定义的engine?: Partial<Engine>与该类型不兼容,触发类型冲突。Omit的第二个参数是字符串联合类型,正确写法是'engine' | 'name',而非'engine | name'(这属于语法错误)。
正确的类型定义方式
方法1:手动构造目标类型
直接组合类型,让顶级属性可选,同时让 engine 支持传入部分嵌套属性:
type MockLocomotive = Partial<Omit<Locomotive, 'engine'>> & { engine?: Partial<Engine>; };
Partial<Omit<Locomotive, 'engine'>>将除engine外的所有Locomotive属性设为可选- 单独定义
engine?: Partial<Engine>,允许传入Engine的任意部分属性
方法2:通用深层Partial类型
如果后续有更多嵌套类型需要支持,可以定义通用的递归Partial类型,复用性更强:
type DeepPartial<T> = { [P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P]; }; // 直接使用该类型作为参数类型 type MockLocomotive = DeepPartial<Locomotive>;
这个 DeepPartial 会递归地将所有嵌套对象的属性设为可选,完美满足任意层级的部分属性传入需求。
完整生成函数示例
结合faker.js实现的 getTrains 函数:
import { faker } from '@faker-js/faker'; type DeepPartial<T> = { [P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P]; }; function getTrains(defaultValues: DeepPartial<Locomotive> = {}): Locomotive { return { name: defaultValues.name ?? faker.company.name(), serialNumber: defaultValues.serialNumber ?? faker.string.alphanumeric(10), engine: { fuel: defaultValues.engine?.fuel ?? faker.helpers.arrayElement(['COAL', 'DIESEL', 'ELECTRIC'] as const), size: defaultValues.engine?.size ?? faker.number.int({ min: 100, max: 1000 }) }, model: defaultValues.model ?? faker.helpers.arrayElement(Object.values(Model)), gauge: defaultValues.gauge ?? faker.number.float({ min: 0.5, max: 2, precision: 0.1 }) }; }
验证用法
可以自由传入任意部分属性:
// 仅传入name const train1 = getTrains({ name: "Test Locomotive" }); // 仅传入engine的fuel属性 const train2 = getTrains({ engine: { fuel: 'ELECTRIC' } }); // 传入多个属性+嵌套engine的size const train3 = getTrains({ model: Model.HORNBY, engine: { size: 500 } });
内容的提问来源于stack exchange,提问作者AncientSwordRage
相关产品推荐
相关产品推荐

