I am trying to replicate the idea of "traits" from PHP into TypeGraphQL types. However, between abstract classes and mixins, I got a bit lost and can't figure out what even to google....
I would like to have a bunch of traits that I can add to my types to reduce the amount of code I write. For example, I'd like a trait that adds an ID
and I'd like a trait that adds timestamps
.
Here's what I got so far: A basic type definition
@ObjectType()
class Hero {
@Field(() => String, {description: "Hello world"})
public name!: string;
@Field(() => String, {nullable: true})
public image!: string;
}
export {Hero};
I have added my first abstract class like this:
@ObjectType({isAbstract: true})
@InputType({isAbstract: true})
class IdTrait extends BaseClass {
@Field(() => ID)
public id!: number;
}
Now, if I add to my basic type class Hero extends IdTrait {...}
, I get to use all 3 fields (ID, name, and image).
If I want to add
@ObjectType({isAbstract: true})
@InputType({isAbstract: true})
class TimestampsTrait {
@Field(() => Date)
public createdAt!: Date;
@Field(() => Date)
public editedAt!: Date;
}
export {Timestamps};
I won't be able to do extends IdTrait, TimestampsTrait
etc...
So I changed my 2 abstract classes to something like this
function withId<TClassType extends ClassType>(BaseClass: TClassType): ClassType {
@ObjectType({isAbstract: true})
@InputType({isAbstract: true})
class IdTrait extends BaseClass {
@Field(() => ID)
public id!: number;
}
return IdTrait;
}
Similar for the timestamps.
I was hoping I can achieve something like this
class Hero extends withId(withTimestamps()) {
// ...
}
But it doesn't work that way.
class Hero extends withId(TimestampsTrait) {...}
This semi-worked. I got the timestamps, but not the ID.
What would be a better way to do this? Given the possibility to have 3+ such "traits".
You need a base class for mixins, like HeroDetails
:
@ObjectType({isAbstract: true})
class HeroDetails {
@Field()
nick!: string;
}
Then you can merge it with mixins:
class Hero extends withId(withTimestamps(HeroDetails)) {
// ...
}