타입스크립트(TypeScript)의 "타입 호환성"은 두 가지 타입 간에 값이 할당 가능한지 여부를 나타내는 개념입니다. 즉, 어떤 타입의 값이 다른 타입으로 변환되거나 할당될 수 있는지를 판단하는 규칙의 모음입니다. 이를 통해 코드 작성 시 불필요한 오류를 방지하고 타입 안정성을 유지할 수 있습니다.
타입스크립트의 타입 호환성은 4가지로 나누어서 이해할 수 있습니다.
타입의 구조적 형태가 얼마나 유사한지를 고려합니다. 즉, 타입유형(type, interface..)이 아닌 타입의 구조(같은 속성과 타입인지)를 통해 호환 유무를 판단합니다. 이를 통해 타입 간에 불필요한 제약 없이 유연한 코드 작성이 가능합니다.
// 인터페이스 A와 B 정의
interface A {
x: number;
}
interface B {
x: number;
y: number;
}
// A는 B로 할당 가능합니다. (넘치는건 가능)
let a: A = { x: 1 };
let b: B = a; // 가능
// B는 A로 할당 불가능합니다. (부족한건 불가능)
let bb: B = { x: 1, y: 2 };
let aa: A = bb; // 오류! Property 'y'가 필요합니다.
함수의 역시 구조적 타이핑 관정에서 함수 구조가 유사하면 호환이 가능합니다. 매개변수와 반환 타입이 다른 함수의 동작을 보장해 줄 수 있다면 해당 함수는 호환이 가능합니다.
type FuncA = (x: number) => number;
type FuncB = (x: number, y: number) => number;
// FuncA는 FuncB로 할당 가능합니다. (매개변수가 적어지는건 가능)
let fnA: FuncA = (x) => x * 2;
let fnB: FuncB = fnA; // 가능
// FuncB는 FuncA로 할당 불가능합니다. (매개변수가 많아지는건 불가능)
let fnBB: FuncB = (x, y) => x + y;
let fnAA: FuncA = fnBB; // 오류! 불필요한 매개변수 'y'가 있습니다.
타입스크립트의 이넘은 직접 값을 할당해주지 않으면 숫자값이 지정이 됩니다. 이러한 숫자형 이넘은 number type과 호환됩니다.
// 이넘의 호환성 예시
enum Direction {
Up, //0
Down, //1
Left, //2
Right, //3
}
let directionValue: Direction;
directionValue = Direction.Up; // 가능
directionValue = 1; // 가능, 숫자 값 할당도 가능
let anotherDirection: Direction;
anotherDirection = "Left"; // 오류! 문자열은 이넘과 호환되지 않습니다.
이넘은 이넘타입간은 호환이 불가능합니다. 따라서 이넘은 구조적 타이핑개념이 적용 되지 않습니다.
enum Color { Red, Green, Blue, } enum Shape { Circle, Square, Triangle, } let colorValue: Color = Color.Red; let shapeValue: Shape = Shape.Circle; colorValue = shapeValue; // 오류! 이넘 타입 간 호환 불가능
제네릭은 받은 타입을 통해 일반적인 타입호환과 같게 동작합니다. 하지만 만약 받은 타입이 해당 구조에서 사용되지 않는다면 타입호환의 영향을 주지 않습니다.
// 제네릭의 호환성 예시
interface Box<T> {
value: T;
}
let box1: Box<number>;
let box2: Box<string>;
box1 = box2; // 오류! 제네릭의 타입이 다르기 때문에 호환되지 않습니다.
// 하지만 제네릭 타입이 실제로 사용되는 경우에는 호환됩니다.
let numBox: Box<number>;
let anyBox: Box<any>;
numBox = anyBox; // 가능, 'any' 타입은 모든 타입과 호환됩니다.