Recently, I've been working on creating a factory for my models in Typescript using the faker package. I was able to develop a functional generic factory similar to the casual package API, which takes a generic model maker and options to customize the created model. This generic factory generates another factory specifically for models. The generated factory can accept two parameters: the first one being the quantity of models to create (default is 1), and the second parameter being the options to be applied to the models. However, I'm facing a challenge in determining the return type of the factory based on the quantity value automatically. Essentially, if the quantity is one, I should return 'IModel', but if it's more than one, I should return 'IModel[]'.
Currently, I am explicitly returning 'IModel | IModel[]', which requires me to specify the return type whenever I utilize the factories:
jest.spyOn(registerUserStub, 'execute').mockResolvedValueOnce(userFactory(1) as IUserModel)
Below is a snippet of my code:
// My User Model
export type IUserModel = {
id: string,
name: string,
email: string,
password: string,
active: boolean,
confirmed: boolean
}
Factory Maker
import { DeepPartial } from 'utility-types'
export function factoryMaker<T = any> (objMaker: (options?: DeepPartial<T>) => T): (quantity: number, options?: DeepPartial<T>) => T | T[] {
return (quantity, options) => {
const entitiesArray = new Array(quantity).fill(null).map(() => objMaker(options))
return quantity === 1 ? entitiesArray[0] : entitiesArray
}
}
My User Factory
import { DeepPartial } from 'utility-types'
import faker from 'faker'
import { IUserModel } from '../models'
import { factoryMaker } from './factoryMaker'
type OptionsType = DeepPartial<IUserModel>
function makeUser (options?: OptionsType):IUserModel {
return {
id: faker.random.uuid(),
password: faker.random.uuid(),
email: faker.internet.email(),
name: faker.name.findName(),
confirmed: options.confirmed !== undefined ? options.confirmed : true,
active: true,
...options
}
}
const userFactory = factoryMaker<IUserModel>(makeUser)
export { userFactory }