首页 > 解决方案 > 如何在打字稿中定义续集关联?

问题描述

我有一个 Product 表和一个 AccountingPeriod 表,其属于从Product.manufacturingPeriodId到 AccountingPeriod.id 的关系。

下面的代码编译但因“模型产品上的属性'manufacturingPeriod'和关联'manufacturingPeriod'之间的命名冲突。要解决这个问题,请在运行时更改foreignKey或在您的关联定义中” 。

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

嗬!对我来说似乎是 Catch-22。

当然,我可以在调用 sequelize.define() 的选项对象中删除ProductAttributes.manufacturingPeriod、放回manufacturingPeriodId: number;和重命名manufacturingPeriod回。manufacturingPeriodId编译和运行都很好,但是我不能myproduct.manufacturingPeriod.startDate在打字稿中编写类似的代码。

我尝试了各种其他方法。一切都失败了,所以我要举起投降的白旗。谁能帮我吗?我有 sequelize 的经验,但对 typescript 来说相对较新,我只是没有看到它。

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

标签: typescriptsequelize.js

解决方案


自己找到了答案。

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

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>


推荐阅读