How to use mixins in TypeGraphQL to replicate “traits” and extend types?

How to use mixins in TypeGraphQL to replicate “traits” and extend types?


1

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".

Share

1 Answer
1

Reset to default


0

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)) {
  // ...
}

Share



Not the answer you're looking for? Browse other questions tagged

or ask your own question.

Leave a Reply

Your email address will not be published. Required fields are marked *