HooneyLog

타입스크립트에서 여러 객체를 상속받을 수 있는 Mixin 패턴을 알아보자!

프로필 이미지

Seunghoon Shin

2022년 4월 29일 01:19

안녕하세요!! 이번 시간에는 Typescript에서 여러개의 객체를 상속받을 수 있게 도와주는 Mixin 패턴에 대해 알아보도록 하겠습니다!!!

그럼 바로 본론으로 들어가보죠~

일반적으로 타입스크립트에서는 객체를 상속받을때 한가지의 객체만 상속이 가능합니다. 만약 여러개의 상속을 받는다면 아래와 같은 에러가 발생합니다

class Men {
  playGame() {
    console.log("게임 시작!")
  }
}

class Women {
  goShopping() {
    console.log("쇼핑하러 고고고~")
  }
}

// error - Classes can only extend a single class.(1174)
class People extends Men, Women {}

만약 이 두가지의 객체를 상속받아 Men과 Women에서 선언한 프로퍼티 메서드를 사용하고 싶다면 어떻게 해야할까??

Mixin을 사용하면 됩니다!

바로 코드로 살펴보죠!

class Men {
  playGame() {
    console.log("게임 시작!")
  }
}

class Women {
  goShopping() {
    console.log("쇼핑하러 고고고~")
  }
}

class People {}

interface People extends Men, Women {};


const applyMixins = (derivedCtor: any, constructors: any[]) => {
	// 배열안에 있는 Men과 Women의 객체들을 순회합니다
  constructors.forEach((baseCtor) => {
	// 각 객체들의 프로퍼티들의 네임들 배열로 만들고 그것을 순회합니다.
	// 위의 코드 같은 경우는 예를들어 Men의 객체를 순회하고 있다면 ['constructor','playGame']
	// Women이라면 ['constructor','playGame']을 순회하게 될 것입니다.
    Object.getOwnPropertyNames(baseCtor.prototype).forEach((name) => {

			// defineProperty는 말그대로 프로퍼티를 정의해주는 메서드입니다.
			// derivedCtor 에 People이라는 객체가 들어갔고, 그 프로퍼티에
			// getOwnPropertyNames 에서 탄생한 배열의 value들을 프로퍼티를 정의해줍니다.
			// 그 프로퍼티들에는 객체들의 속성을 넣어주는 것이죠! 속성이 없다면 빈 객체를 넣어줍니다
		
			// getOwnPropertyDescriptor 로 탄생한 객체의 속성은 이러한 형태가 됩니다.
			// {
			//   "writable": true,
			//   "enumerable": false,
			//   "configurable": true
			// }
      Object.defineProperty(
        derivedCtor.prototype,
        name,
        Object.getOwnPropertyDescriptor(baseCtor.prototype, name) ||
          Object.create(null)
      );
    });
  });
}

applyMixins(People,[Men,Women]);

const people = new People()

// console.log("쇼핑하러 고고고~")
console.log(people.goShopping())

// console.log("게임 시작!")
console.log(people.playGame())

위의 코드 처럼 하면 다수의 객체를 상속 받을 수 있으며 자유롭게 객체들의 메서드들을 사용하면서 유연하게 개발을 할 수 있습니다!!

이렇게 간단하게 타입스크립트에서 mixin 패턴을 활용하여 여러 객체를 상속 받는 방법에 대해 알아보았습니다!

감사합니다!