본문 바로가기
언어/TypeScript

타입 호환성

by seacode 2025. 4. 15.

타입 호환

타입스크립트 코드에서 특정 타입의 호환성을 의미한다. 아래코드는 타 언어였다면 바로 에러가 일어났을 것이다.

interface Ironman { name: string; }

class Avengers { name: string; }

let m: Ironman;
m = new Avengers();

하지만 JS는 기본적으로 객체 리터럴, 익명함수 등을 사용하므로 명시적인 타입 지정보다 코드의 구조 관점에서 타입을 지정하는 것이 나은 편이다.

 

구조적 타이핑

  • 코드 구조 관점에서 서로 호환되는지를 판단하는 것.
interface Avengers {
  name: string;
}

let hero: Avengers;
// 타입스크립트가 추론한 타입은 { name: string; location: string; } 입니다.
let Iron = { name: "Ironman", location: "Pangyo" };
hero = Iron;
  • 위 코드에서 Iron이 hero와 호환되는 이유는 속성 중에 name이 공통되기 때문. 따라서 Iron 이 Avengers 와 호환된다.
  • 함수 호출 시에도 마찬가지.
function assemble(a: Avengers) {
  console.log("Avengers assemble", a.name, a.location);
}
//타입 추론: { name: string; location: string; }
assemble(Iron);

Soundness

타입스크립트는 컴파일 시점에 타입을 추론할 수 없는 타입에 대해서는 안전하다고 간주한다. 이를 soundness 하다고 한다.

Enum 타입 호환

Enum 타입은 number 타입과 호환되지만, enum 끼리는 호환되지 않는다.

enum Status { Ready, Waiting };
enum Color { Red, Blue, Green };

let status = Status.Ready;
status = Color.Green;  // Error

클래스 타입 호환

클래스 타입은 클래스 타입끼리 비교할 때 static member와 생성자를 제외하고 속성만 비교한다.

class Hulk {
  handSize: number;
  constructor(name: string, numHand: number) { }
}

class Captain {
  handSize: number;
  constructor(numHand: number) { }
}

let a: Hulk;
let s: Captain;

a = s;  // OK
s = a;  // OK

즉, 구조적으로 동일한 타입 handsize 를 가지므로 서로 호환된다.

제네릭 타입 호환

제네릭 타입 간 호환 여부는 <T> 가 속성에 할당 되었는지를 기준으로 한다.

interface Empty<T> {
}
let x: Empty<number>;
let y: Empty<string>;

x = y;  // OK, because y matches structure of x

해당 예시는 속성이 없으므로 서로 같은 타입으로 간주된다.

interface NotEmpty<T> {
  data: T;
}
let x: NotEmpty<number>;
let y: NotEmpty<string>;

x = y;  // Error, because x and y are not compatible

그런데 이처럼 속성이 있어서 제네릭의 타입 인자가 속성에 할당된다면 서로 다른 타입으로 간주된다.

'언어 > TypeScript' 카테고리의 다른 글

Type Assertion (as 사용법)  (0) 2025.04.16
type vs interface  (0) 2025.04.16
타입 추론  (0) 2025.04.15
제네릭(Generics)  (0) 2025.04.15
Class 특성  (0) 2025.04.14