인프런 커뮤니티 질문&답변

Chang Su Lee님의 프로필 이미지
Chang Su Lee

작성한 질문수

Node.js에 TypeScript 적용하기(feat. NodeBird)

라우터 완성하기

Sequelize Association 오류

작성

·

391

·

수정됨

0

start로 시작한 서버에서는 sequelize가 정상 작동하는데 test를 하면 아래와 같은 오류가 발생합니다

 FAIL  tests/integration/intergration.test.ts
  ● Test suite failed to run

    TypeError: Cannot read properties of undefined (reading 'name')

      74 |     }
      75 |     static associate() {
    > 76 |         User.hasMany(Box_1.default, {
         |              ^
      77 |             sourceKey: "id",
      78 |             foreignKey: "UserId"
      79 |         });

      at new HasMany (node_modules/sequelize/src/associations/has-many.js:51:37)
      at Function.hasMany (node_modules/sequelize/src/associations/mixin.js:34:25)
      at Function.associate (models/user.js:76:14)
      at Object.<anonymous> (models/index.js:26:19)
      at Object.<anonymous> (tests/integration/intergration.test.ts:2:1)

Test Suites: 1 failed, 1 total
Tests:       0 total
Snapshots:   0 total
Time:        2.43 s
Ran all test suites.

sequelize 공식 문서를 보고 그대로 적용해 고쳐보았지만 무엇이 문제인지 잘 모르겠습니다 stackoverflow에서는 sequelize의 오류라고 하는 것 같은데 현재 저의 수준에서는 대화의 내용조차 잘 감이 잡히지 않습니다...

공식 문서를 보고 association들을 수정하면 TypeError: Cannot read properties of undefined (reading 'name') 에서 name이 UserId 등으로 바뀐 것도 몇번 보았지만 공식문서에서 나온대로 수정하면 다시 'name'을 읽을때 찾을 수 없다고 나옵니다. 또한

at new HasMany (node_modules/sequelize/src/associations/has-many.js:51:37)

at Function.hasMany (node_modules/sequelize/src/associations/mixin.js:34:25) 은 들어갈 수 없는 파일처럼 보입니다.

import Sequelize, {
  CreationOptional,
  InferAttributes,
  InferCreationAttributes,
  Model,
  ForeignKey,
} from "sequelize";
import {
  HasManyAddAssociationMixin,
  HasManyCountAssociationsMixin,
  HasManyCreateAssociationMixin,
  HasManyGetAssociationsMixin,
  HasManyHasAssociationMixin,
} from "sequelize/types/associations";
import Bookmark from "./bookmark.js";
import User from "./user.js";

class Box extends Model<InferAttributes<Box>, InferCreationAttributes<Box>> {
  declare id: CreationOptional<number>;
  declare box: string;
  declare img: string;
  declare createdAt: CreationOptional<Date>;
  declare updatedAt: CreationOptional<Date>;

  declare UserId: ForeignKey<User["id"]>;

  declare getBookmarks: HasManyGetAssociationsMixin<Bookmark>;
  declare addBookmarks: HasManyAddAssociationMixin<Bookmark, number>;
  declare hasBookmarks: HasManyHasAssociationMixin<Bookmark, number>;
  declare countBookmarks: HasManyCountAssociationsMixin;
  declare createBookmarks: HasManyCreateAssociationMixin<Bookmark>;

  static initiate(sequelize: Sequelize.Sequelize) {
    Box.init(
      {
        id: {
          type: Sequelize.INTEGER,
          primaryKey: true,
          autoIncrement: true,
        },
        box: {
          type: Sequelize.STRING(15),
          allowNull: false,
        },
        img: {
          type: Sequelize.STRING(200),
          allowNull: true,
        },
        createdAt: Sequelize.DATE,
        updatedAt: Sequelize.DATE,
      },
      {
        sequelize,
        timestamps: true,
        underscored: false,
        modelName: "Box",
        tableName: "boxs",
        paranoid: false,
        charset: "utf8mb4",
        collate: "utf8mb4_general_ci",
      }
    );
  }

  static associate() {
    Box.belongsTo(User, { targetKey: "id" });
    Box.hasMany(Bookmark, {
      sourceKey: "id",
      foreignKey: "BoxId",
    });
  }
}

export default Box;

box.ts입니다

import Sequelize, {
  CreationOptional,
  InferAttributes,
  InferCreationAttributes,
  Model,
} from "sequelize";
import {
  HasManyAddAssociationMixin,
  HasManyCountAssociationsMixin,
  HasManyCreateAssociationMixin,
  HasManyGetAssociationsMixin,
  HasManyHasAssociationMixin,
} from "sequelize/types/associations";
import Box from "./Box";

class User extends Model<InferAttributes<User>, InferCreationAttributes<User>> {
  declare id: CreationOptional<number>;
  // 'CreationOptional' is a special type that marks the field as optional
  // id can be undefined during creation when using `autoIncrement`
  declare email: string;
  declare nick: string;
  declare password: CreationOptional<string>;
  declare provider: CreationOptional<string>;
  declare snsId: CreationOptional<string>;
  declare createdAt: CreationOptional<Date>;
  // createdAt can be undefined during creation
  declare updatedAt: CreationOptional<Date>;
  // updatedAt can be undefined during creation
  declare deletedAt: CreationOptional<Date>;
  // ...

  declare getBoxs: HasManyGetAssociationsMixin<Box>;
  declare addBoxs: HasManyAddAssociationMixin<Box, number>;
  declare hasBoxs: HasManyHasAssociationMixin<Box, number>;
  declare countBoxs: HasManyCountAssociationsMixin;
  declare createBoxs: HasManyCreateAssociationMixin<Box>;

  static initiate(sequelize: Sequelize.Sequelize) {
    User.init(
      {
        id: {
          type: Sequelize.INTEGER,
          primaryKey: true,
          autoIncrement: true,
        },
        email: {
          type: Sequelize.STRING(40),
          allowNull: true,
          unique: true,
        },
        nick: {
          type: Sequelize.STRING(15),
          allowNull: false,
        },
        password: {
          type: Sequelize.STRING(100),
          allowNull: true,
        },
        provider: {
          type: Sequelize.ENUM("local", "kakao", "github"),
          allowNull: false,
          defaultValue: "local",
        },
        snsId: {
          type: Sequelize.STRING(30),
          allowNull: true,
        },
        createdAt: Sequelize.DATE,
        updatedAt: Sequelize.DATE,
        deletedAt: Sequelize.DATE,
      },
      {
        sequelize,
        timestamps: true,
        underscored: false,
        modelName: "User",
        tableName: "users",
        paranoid: true,
        charset: "utf8",
        collate: "utf8_general_ci",
      }
    );
  }

  static associate() {
    User.hasMany(Box, {
      sourceKey: "id",
      foreignKey: "UserId"
    });
  }
}

export default User;

user.ts입니다

 

답변 2

0

Chang Su Lee님의 프로필 이미지
Chang Su Lee
질문자

association 오류가 아니라 tsc로 컨버트된 const Box_1 = __importDefault(require("./Box."));에서 "./Box.js"를 불러오는게 아니었기 때문에 오류가 발생했습니다.

chatGPT한테 몇가지 질문을 던져봤는데 성능이 엄청나네요 답변은 다음과 같습니다.

--

Error message인 "TypeError: Cannot read properties of undefined (reading 'name')" 는 그 코드에서 "name" property를 접근하려고 할 때 undefined object를 접근하려고 할 때 발생한다는 것을 의미합니다.

User.hasMany 메소드 호출이 발생한 코드인 models/user.js 파일의 associate 함수에서 Box_1.default 객체가 undefined 상태로 전달되어서 생긴 문제 같습니다. Box_1 모듈이 제대로 import 되었고, default export가 "name" property를 가진 object 인지 확인해주세요.

--

이전에 질문했던 내용도 그렇고 box.ts만 Box같이 대문자로 변형되고 뒤에 .js도 안붙는데 혹시 이게 어떤 원인에서 발생하는 오류인지 아시나요?

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

전혀 감을 못 잡겠습니다. box만 안 될 이유가 없을텐데요. 기존 거 지우고해도 똑같나요?

Chang Su Lee님의 프로필 이미지
Chang Su Lee
질문자

https://stackoverflow.com/questions/36628612/typescript-transpiler-casing-issue

이전에 Box한번 ts를 컨버트 했던게 문제였던것 같습니다.

tsconfig에서 "forceConsistentCasingInFileNames": true로 설정하고 문제 해결했습니다 답변 갑사합니다!!

--

문제 해결하기 전까지는 지우고 다시 생성해도 똑같이 uppercase로 컨버트 되어서 나왔었습니다

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

아, 저는 항상 켜놓는 옵션이라 미처 생각을 못했네요. 해결되셔서 다행입니다. 저 옵션도 항상 켜두세요.

Chang Su Lee님의 프로필 이미지
Chang Su Lee
질문자

네 답변 갑사합니다!

0

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

at new HasMany (node_modules/sequelize/src/associations/has-many.js:51:37)

at Function.hasMany (node_modules/sequelize/src/associations/mixin.js:34:25)

여기에 들어갈 수 있습니다. 저 경로로 직접 들어가시면 됩니다. 해당 name이 어떤 객체의 속성인지 파악하는게 중요합니다.

Chang Su Lee님의 프로필 이미지
Chang Su Lee

작성한 질문수

질문하기