如何在打字稿中定义续集关联?

Bil*_*lyB 9 sequelize.js typescript

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

下面的代码可以编译,但会因“模型产品上的属性‘manufacturingPeriod’和关联‘manufacturingPeriod’之间的命名冲突而崩溃。要解决此问题,请在运行时更改foreignKey或如关联定义中的那样”。

如果我as按照指示更改最底部的关联代码,我也会爆炸,但这次“AccountingPeriod 使用别名与产品关联。您已包含别名 (accountingPeriod),但它与别名不匹配”在您的协会中定义”。第二条错误消息特别令人费解,因为我没有指定名为accountingPeriod的别名。

哎哟!对我来说似乎是第 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'
    });
}
Run Code Online (Sandbox Code Playgroud)

Bil*_*lyB 8

我自己找到了答案。

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

export interface ProductInstance extends Sequelize.Instance<ProductAttributes>, ProductAttributes {
    manufacturingPeriod: AccountingPeriodInstance;
}
Run Code Online (Sandbox Code Playgroud)

在调试时,我还注意到了方便的 getXXX、setXXX、createXXX、addXXX、removeXXX、hasXXX 和 countXXX 访问器函数,这些函数会自动为关系创建sequelize;我已经忘记他们了。经过一番挖掘后,我在 @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>;
}
Run Code Online (Sandbox Code Playgroud)

在这个特殊的例子中,关系是belongsTo,所以getXXX、setXXX、createXXX是仅有的3个函数。{RelationShipType}{Add}AssociationMixin<TInstance>但还有更多以、{RelationShipType}{Remove}AssociationMixin<TInstance>等形式存在。