import { Type } from "@nestjs/common";
/**
* Type = interface Type<T = any> extends Function {
new (...args: any[]): T;
}
*/
/**
* Stores references to input types created recursively.
*/
export function memoizeInputClass<T, ReturnType>(
keyGenerator: (classRef: Type) => string,
fn: (
key: string,
EntityClass: Type<T>,
classRef: Type<ReturnType>,
) => Type<ReturnType>,
): (classRef: Type<T>) => Type<ReturnType> {
const typeStorage = new Map<string, Type<ReturnType>>();
return function (classRef: Type<T>) {
const key = keyGenerator(classRef);
const mappedValue = typeStorage.get(key);
if (mappedValue) {
return mappedValue;
}
const classConst = class {} as Type<ReturnType>;
Object.defineProperty(classConst, "name", {
value: key,
});
typeStorage.set(key, classConst);
return fn(key, classRef, classConst);
};
}
#Issue with Type Generic not bubbling up
4 messages · Page 1 of 1 (latest)
import { QueryOrder } from "@mikro-orm/core";
import { Type } from "@nestjs/common";
import { Field, InputType, registerEnumType } from "@nestjs/graphql";
import { getFieldsAndDecoratorForType } from "@nestjs/graphql/dist/schema-builder/utils/get-fields-and-decorator.util";
import { memoizeInputClass } from "../../storages/input-class.storage";
export type IOrderByInput<T> = {
[K in keyof T]: QueryOrder;
};
/**
* Allows us to create an InputType for MikroORM entities that applies each
* field with the QueryOrder enum field value type.
*/
const OrderByInput = memoizeInputClass(
(classRef) => `${classRef.name}OrderByInput`,
function <T>(
inputName: string,
TClass: Type<T>,
OrderByType: Type<IOrderByInput<T>>,
): Type<IOrderByInput<T>> {
const { fields } = getFieldsAndDecoratorForType(TClass);
InputType(inputName)(OrderByType);
fields.forEach((item) => {
const returnType = item.extensions?.relation
? OrderByInput(item.typeFn() as Type)
: QueryOrder;
/**
* Takes the field name and dictates that GraphQL expects a `QueryOrder`
* as the value input
*/
Field(() => returnType, { nullable: true })(
OrderByType.prototype,
item.name,
);
});
return OrderByType;
},
);
export { OrderByInput };
However, when I attempt to use OrderByInput, I get the following:
@ObjectType()
class Foo {
@Field(() => ID)
id: number;
}
@InputType()
class FooOrderByInput extends OrderByInput(Foo) {} // const OrderByInput: (classRef: Type<unknown>) => Type<unknown>
How can I resolve this so that it instead returns const OrderByInput: (classRef: Type<Foo>) => Type<IOrderByInput<Foo>> when calling OrderByInput(Foo)?
I'm sure it's due to how I've defined momoizeInputClass, but I'm unsure how