如何在打字稿中定义序列化关联?

时间:2018-10-31 19:00:09

标签: typescript sequelize.js

我有一个Product表和一个AccountingPeriod表,从Product.manufacturingPeriodId到AccountingPeriod.id具有 belongsTo 关系。

下面的代码可以编译,但在“模型Product上属性'manufacturingPeriod'和关联'manufacturingPeriod'之间的命名冲突。为此,请更改ForeignKey或按照关联定义进行更改” 运行时间。

如果我按照指示在底部的关联代码中更改了as,我也会感到震惊,但这一次是“ AccountingPeriod使用别名与Product关联。您已经包括了别名(accountingPeriod),但与您的关联中定义的别名不匹配。” 第二条错误消息尤其令人困惑,因为我没有指定名为 accountingPeriod 的别名。

Do!在我看来就像是Catch-22。

当然,我可以在调用sequelize.define()的选项对象中删除ProductAttributes.manufacturingPeriod,放回manufacturingPeriodId: number;并将manufacturingPeriod重命名为manufacturingPeriodId。可以编译并正常运行,但是随后我无法在打字稿中编写类似myproduct.manufacturingPeriod.startDate的代码。

我尝试了其他各种方法。所有人都失败了,所以我举起了投降的白旗。谁能帮我吗?我有续集方面的经验,但对打字稿来说还比较陌生,但我只是看不到它。

import * as Sequelize from 'sequelize';
import {ObjectRelationalManager as orm} from '../index';
import {AccountingPeriodInstance} from './accounting-period';

export interface ProductAttributes {
    id?: number;
    name: string;
    manufacturingPeriod: AccountingPeriodInstance;
}

export interface ProductInstance extends Sequelize.Instance<ProductAttributes>, ProductAttributes {}

export default (
    sequelize: Sequelize.Sequelize,
    dataTypes: Sequelize.DataTypes
): Sequelize.Model<ProductInstance, ProductAttributes> => {
    return sequelize.define<ProductInstance, ProductAttributes>(
        'Product',
        {
            id: {
                type: dataTypes.INTEGER,
                field: 'id',
                allowNull: false,
                primaryKey: true,
                autoIncrement: true
            },
            name: {
                type: dataTypes.STRING(20),
                field: 'name',
                allowNull: false
            },
            manufacturingPeriod: {
                type: dataTypes.INTEGER,
                field: 'manufacturingPeriodId',
                allowNull: false,
                references: {
                    model: 'AccountingPeriod',
                    key: 'id'
                },
                onDelete: 'NO ACTION',
                onUpdate: 'NO ACTION'
            }
        },
        {
            tableName: 'Product'
        }
    );
};

export function createAssociations(): void {
    orm.Product.belongsTo(orm.AccountingPeriod, {
        as: 'manufacturingPeriod',
        // foreignKey: 'manufacturingPeriodId',
        targetKey: 'id',
        onDelete: 'NO ACTION',
        onUpdate: 'NO ACTION'
    });
}

1 个答案:

答案 0 :(得分:0)

自己找到答案。

Sequelize已经为关系创建了属性,因此只需在ProductInstance定义中为打字稿编译器声明它们即可:

export interface ProductInstance extends Sequelize.Instance<ProductAttributes>, ProductAttributes {
    manufacturingPeriod: AccountingPeriodInstance;
}

在调试时,我还注意到方便地自动为关系创建的getXXX,setXXX,createXXX,addXXX,removeXXX,hasXXX和countXXX访问器函数。我忘了他们。经过一番挖掘,我在@ types / sequelize的类型定义文件中找到了它们的打字稿定义:

export interface ProductInstance extends Sequelize.Instance<ProductAttributes>, ProductAttributes {
    manufacturingPeriod: AccountingPeriodInstance;
    getAccountingPeriod: Sequelize.BelongsToGetAssociationMixin<AccountingPeriodInstance>;
    setAccountingPeriod: Sequelize.BelongsToSetAssociationMixin<AccountingPeriodInstance, number>;
    createAccountingPeriod: Sequelize.BelongsToCreateAssociationMixin<AccountingPeriodAttributes>;
}

在这种特殊情况下,关系是belongsTo,因此getXXX,setXXX和createXXX是仅有的3个函数。但是还有更多形式为{RelationShipType}{Add}AssociationMixin<TInstance>{RelationShipType}{Remove}AssociationMixin<TInstance>等。