Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to add anottations to typescript decorators #487

Closed
CampaUTN opened this issue Nov 28, 2018 · 4 comments
Closed

How to add anottations to typescript decorators #487

CampaUTN opened this issue Nov 28, 2018 · 4 comments

Comments

@CampaUTN
Copy link

CampaUTN commented Nov 28, 2018

I'm trying to extend a class by adding methods and attributes through typescript annotations

My problem is that I cannot set sequelize annotations to the new attribute (comment), so it wont be persisted

Is there any chance of make it work?

Maybe it's not the best place to ask, but I've been researching a lot and couldnt find any answer, and also I found out that TypeORM does support this feature easily so maybe there is a chance of making it work

export function EntityWithComments(target: any): ClassDecorator {
    return function (constructor: any) {
        target.prototype['comment'] = 'commentValue';
        target.prototype['getComment'] = function () {  
               //...
       }
  }
}

@EntityWithComments(ConcreteEntity)
@Table
export class ConcreteEntity extends Entity {
    @Column
    fromDate: Date;
}

export class Entity extends Model<Entity> {
    @PrimaryKey
    @AutoIncrement
    @Column
    id: number;

    @Column
    createdAt: Date;

    @Column
    updatedAt: Date;

    @Column
    deletedAt: Date;
}
@RobinBuschmann
Copy link
Member

Hey @CampaUTN what exactly do you want achieve? A comment per column as discussed here sequelize/sequelize#3553 or just a column comment?

Regarding decorators: They won‘t add types to the class you decorated (microsoft/TypeScript#4881). So best is to go with mixins instead.

@CampaUTN
Copy link
Author

Hi! What I want is to persist 'ConcreteEntity' and to have a 'comment' column (just a regular attribute).
I also tried using mixins but they are kind of similar, it returns a function where it's not possible to use annotations

@RobinBuschmann
Copy link
Member

RobinBuschmann commented Nov 29, 2018

@CampaUTN Ok, here we go:

First, we need some helpers:

// utils.ts
export type MixinType<T> = T extends new(...args: any[]) => infer R ? R : any;
export type Constructor<T = {}> = new (...args: any[]) => T;

Mixins with decorators:

// withComment.ts
import {Column} from "sequelize-typescript";
import {Constructor} from "./utils";

export const withComment = <TBase extends Constructor>(Base: TBase) => {
  class WithComment extends Base {
    @Column comment: string;
  }
  return WithComment;
};
// withLove.ts
import {Column} from "sequelize-typescript";
import {Constructor} from "./utils";

export const withLove = <TBase extends Constructor>(Base: TBase) => {
  class WithLove extends Base {
    @Column love: string;
  }
  return WithLove;
};

Definition of our mixed model:

// User.ts
import {Column, Model, Table} from "sequelize-typescript";
import {withComment} from "../mixins/withComment";
import {withLove} from "../mixins/withLove";
import {MixinType} from "../mixins/utils";

@Table({tableName: 'User'})
class InternalUser extends Model<InternalUser> {

  @Column name!: string;
}

export const User = withComment(withLove(InternalUser)); // Creates actual mixed class
export type User = MixinType<typeof User>; // Creates type for mixin

This might also help you: https://blog.mariusschulz.com/2017/05/26/typescript-2-2-mixin-classes

If you still have any questions don't hesitate to ask!

@CampaUTN
Copy link
Author

CampaUTN commented Dec 3, 2018

@RobinBuschmann It's amazing and works like a charm. Thank you so much!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants