Allow Transient Fields in `defineTypeFactory`
mizdra opened this issue · 1 comments
Problem
Currently, Transient Fields are only allowed in defineTypeFactoryWithTransientFields
.
declare function defineAuthorFactoryWithTransientFields<
_TransientFieldsResolver extends TransientFieldsResolver<Author, Record<string, unknown>>,
TOptions extends AuthorFactoryDefineOptions<ResolvedFields<_TransientFieldsResolver>>,
>(
transientFields: _TransientFieldsResolver,
options: TOptions,
): AuthorFactoryInterface<ResolvedFields<_TransientFieldsResolver>, TOptions>;
const BookFactory = defineBookFactory({
defaultFields: {
id: lazy(({ seq }) => `Book-${seq}`),
title: lazy(({ seq }) => `ゆゆ式 ${seq}巻`),
author: undefined,
},
});
const AuthorFactory = defineAuthorFactoryWithTransientFields(
{
bookCount: 0,
},
{
defaultFields: {
id: lazy(({ seq }) => `Author-${seq}`),
name: '三上小又',
books: lazy(async ({ get }) => {
const bookCount = await get('bookCount');
// eslint-disable-next-line max-nested-callbacks
return Promise.all(Array.from({ length: bookCount }, async () => BookFactory.build()));
}),
},
},
);
This confuses users as they have to use an unusual API. In addition, it is awkward to have to add one more argument.
Solution
I want defineTypeFactory
to allow Transient Fields. The user specifies the type of Transient Fields using the type argument. Also, the default value of Transient Fields is specified by the defaultFields
option.
declare function defineAuthorFactory<
TransientFields extends Record<string, unknown>,
TOptions extends AuthorFactoryDefineOptions<TransientFields>,
>(
options: TOptions,
): AuthorFactoryInterface<TransientFields, TOptions>;
const BookFactory = defineBookFactory({
defaultFields: {
id: lazy(({ seq }) => `Book-${seq}`),
title: lazy(({ seq }) => `ゆゆ式 ${seq}巻`),
author: undefined,
},
});
type BookTransientFields = {
bookCount: number;
};
const AuthorFactory = defineAuthorFactory<BookTransientFields>({
defaultFields: {
id: lazy(({ seq }) => `Author-${seq}`),
name: '三上小又',
books: lazy(async ({ get }) => {
const bookCount = await get('bookCount');
// eslint-disable-next-line max-nested-callbacks
return Promise.all(Array.from({ length: bookCount }, async () => BookFactory.build()));
}),
bookCount: 0,
},
});
Additional context
As you can see from the sample code, defineTypeFactory
currently has a type argument TOptions
. This type argument is inferred from the type of the options
argument. This allows the user to strictly type the return value of defineTypeFactory
without having to specify the type argument.
However, it causes problems when TransientFields
is added to the type arguments of defineTypeFactory
. The user must explicitly pass the type TransientFields
from the function caller, but then the type of the options
argument is not inferred.
TypeScript does not support partial inference of type arguments. Therefore, an implementation of this feature is currently not possible. We will probably have to wait for the following issue to be resolved.