백엔드/Node.js

[TS] 타입 체킹 - 덕 타이핑(Duck Typing, Structural SubTyping)이란?

SparkIT 2025. 4. 9. 23:04

덕 타이핑(Duck Typing)이란?

오리처럼 걷고, 오리처럼 꽥꽥대면, 그건 오리다

 

위와 같은 논리가 타입스크립트에서 사용되는 덕 타이핑입니다. 즉, 타입에 대한 형식만 맞으면 그 타입으로 간주하겠다는 방식입니다. 타입스크립트에서는 값의 형태에 기반하아여 타입 체크가 이루어져야 한다는 가치관이 존재하기 때문입니다. 그래서 구조적 형식 시스템(Structural SubTyping)이라고도 불립니다.

 

예시)

type Person = {
  name: string;
  age: number;
};

const user = {
  name: 'Alice',
  age: 25,
  email: 'alice@example.com'
};

function greet(p: Person) {
  console.log(`Hi, ${p.name}. You are ${p.age} years old.`);
}

greet(user); // ✅ OK!

위 코드에서 greet 함수는 파라미터로 Person 타입을 받아야 합니다. 하지만 user는 따로 Person이라는 타입이 설정되어 있지 않은 object입니다. 하지만 user 변수는 Person 타입이 가지고 있는 name, age를 key로 가지고 있기 때문에 Person이라고 불러도 ok입니다. Person 타입이 가지고 있지 않은 email 이라는 key값을 가지고 있어도 말이죠. 이런 이유로 위 코드에서는 타입 관련 에러가 발생하지 않습니다.

여기서 신경써야할 부분은 user 변수 자체를 선언 및 초기화할 때는 Person 타입을 지정할 수는 없다는 것입니다.

type Person = {
  name: string;
  age: number;
};

const user : Person = {
  name: 'Alice',
  age: 25,
  email: 'alice@example.com' // ❌ 에러!
}

덕 타이핑은 객체 리터럴에 직접 타입을 지정하는 과정에서는 엄격하게 검사를 진행합니다. 하지만 값을 할당하는 과정에서는 단순히 구조만 체크하조. 즉, 값 할당 과정에서만 덕 타이핑이 가능한 것입니다.

 

 

명시적 인터페이스 vs 덕 타이핑

JAVA같은 언어는 클래스나 인터페이스를 명시적으로 상속해야 타입으로 인정됩니다. 하지만 Typescript는 덕 타이핑으로 명확한 인터페이스가 설정되지 않아도 됩니다. 예시 코드를 통해 비교해보겠습니다.

 

명시적 인터페이스

interface Dog {
  name: string;
  bark(): void;
}

class MyDog implements Dog {
  name = 'Buddy';

  bark() {
    console.log('Woof!');
  }
}

const dog: Dog = new MyDog(); // ✅ OK: Dog 인터페이스를 구현했기 때문

new MyDog()를 통해 만들어진 dog는 Dog 타입입니다. 왜냐하면 MyDog라는 클래스는 Dog 인터페이스를 implements했기 때문입니다.

 

 

덕 타이핑

interface Dog {
  name: string;
  bark(): void;
}

const strayDog = {
  name: 'Stray',
  bark() {
    console.log('Bark!');
  },
  color: 'black' // 인터페이스에 없는 필드
};

const dog: Dog = strayDog; // ✅ OK: 구조가 맞으면 통과

strayDog는 Dog 인터페이스처럼 name과 bark()라는 key값을 가지고 있습니다. 그리고 strayDog는 이런 값을 그대로 dog 변수에 복사하조. 이때 dog는 Dog 인터페이스와 완전 동일한 구조를 가지고 있지 않지만 Dog의 key값을 모두 가지고 있기 때문에 Dog 타입으로 인정됩니다.