Sequelize-typescript: How to add anottations to typescript decorators

Created on 28 Nov 2018  路  4Comments  路  Source: RobinBuschmann/sequelize-typescript

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;
}

Most helpful comment

@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;
};

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

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

Definition of our mixed model:
```ts
// 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!

All 4 comments

Hey @CampaUTN what exactly do you want achieve? A comment per column as discussed here https://github.com/sequelize/sequelize/issues/3553 or just a column comment?

Regarding decorators: They won鈥榯 add types to the class you decorated (https://github.com/Microsoft/TypeScript/issues/4881). So best is to go with mixins instead.

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

@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;
};

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

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

Definition of our mixed model:
```ts
// 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!

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

Was this page helpful?
0 / 5 - 0 ratings

Related issues

thestrayed picture thestrayed  路  5Comments

KAMAELUA picture KAMAELUA  路  4Comments

samanmohamadi picture samanmohamadi  路  5Comments

nandox5 picture nandox5  路  3Comments

lverledens picture lverledens  路  4Comments