관리 메뉴

학습하며 정리하는 개발블로그

Class 메서드 추가 후 Plain Object에서 발생하는 ‘Missing Property’ 오류 본문

타입스크립트

Class 메서드 추가 후 Plain Object에서 발생하는 ‘Missing Property’ 오류

쩌리Dev 2025. 1. 31. 22:18

1. 개요

a. 배경

  • Class에 function을 추가하였는데 Class를 PlainObject로 생성하고 사용되어지던 코드에서 전부 오류가 발생 되었습니다.
  • 오류 내용은 “missing property” 이였습니다.
  • Jvm기반으로 개발을 하던 저에게는 생소해서 찾아보니 Java에서의 Class와 Typescript의 Class의 차이점이 있다라는 것을 알게 되었습니다.

=> Typescript의 Class는 필드뿐만 아니라 메서드도 실제 객체에 존재를 해야한다는 것이였습니다.

2. 개념 정리 🧐

  • Typescirpt에 대해서 모르는 개념들이 있는것이 문제인듯 하여서 관련 개념들을 정리해보았습니다. 

a.  Property

  • JavaScript/TypeScript에서는 객체에 포함된 모든 key-value 쌍을 “프로퍼티”라고 부릅니다.
    • 예) obj = { a: 10, b: 20, greet: () => console.log("hi") }에서 a, b, greet가 모두 프로퍼티.
    • 메서드(함수)도 결국 “값(function)을 갖는 프로퍼티”라는 점이 자바와 다릅니다.

b. Class와 Plain Object의 차이

  • Class 인스턴스: new MyClass()로 생성된 객체. 내부적으로 MyClass.prototype을 상속받아, 선언된 메서드 등을 자동으로 갖게 됩니다.
  • Plain Object(객체 리터럴): { ... } 형태로 생성된 단순 객체.
    • 클래스의 프로토타입이나 메서드를 전혀 물려받지 않으며, 사용자가 직접 프로퍼티를 추가하지 않는 한 존재하지 않습니다.
  • TypeScript의 타입: “해당 객체가 MyClass 타입이라면, 클래스에 정의된 모든 필드·메서드를 포함해야 한다”고 판단함.
// (1) class 정의
class MyClass {
  field1: string;
  field2: string;

  constructor(f1: string, f2: string) {
    this.field1 = f1;
    this.field2 = f2;
  }

  // 나중에 추가된 메서드
  someMethod(): void {
    console.log("I'm a new method!");
  }
}

// (2) Plain Object로 "MyClass"를 흉내낸 코드
const obj: MyClass = {
  field1: "Hello",
  field2: "World"
  // 'someMethod'는 없음
};

// (3) 컴파일 시 오류 발생
// =>  Property 'someMethod' is missing in type
//     '{ field1: string; field2: string }'
//     but required in type 'MyClass'.

 

3. 해결방법 

a.  Plain Object 사용 지양 → 실제 Class 인스턴스 사용

가장 권장되는 해결책입니다. Java 개발자라면 더 익숙할 것이고, 클래스에 새로운 메서드를 추가해도 obj는 자동으로 그 메서드를 사용할 수 있습니다.

 

// 잘못된 코드
const obj: MyClass = {
  field1: "Hello",
  field2: "World"
};

// 수정된 코드
const obj = new MyClass("Hello", "World");

b.  Optional 메서드로 선언 (비추)

 “Plain Object에는 메서드가 없어도 괜찮다”는 상황이라면, 클래스·인터페이스 측에서 메서드를 optional로 선언하는 방법이 있습니다.

하지만 클래스 문법과 선택적 메서드는 어색하고, 내부 로직에서 this.someMethod를 호출할 때 에러가 날 수 있으므로 주의가 필요합니다.

class MyClass {
  field1: string;
  field2: string;
  someMethod?(): void; // 선택적 메서드

  constructor(f1: string, f2: string) {
    this.field1 = f1;
    this.field2 = f2;
  }
}

 

b. 데이터만 필요한 경우, Interface로 별도 정의

 실제로는 “메서드가 없는 객체”와 “메서드가 필요한 클래스 객체”를 분리하는 방법입니다.

interface MyData {
  field1: string;
  field2: string;
}

class MyClass {
  field1: string;
  field2: string;
  someMethod() { ... }
  ...
}