// sub1 타입은 sup1 타입의 서브 타입이다.
let sub1: 1 = 1; // 리터럴타입으로 숫자 1입니다. 그래서 숫자 1만 넣을 수 있습니다.
let sup1: number = sub1; // sup1에는 sub1을 넣을 수 있습니다.
sub1 = sup1; // error! Type 'number' is not assignable to type '1'.
// sub2 타입은 sup2 타입의 서브 타입이다.
let sub2: number[] = [1];
let sup2: object = sub2; // Array도 object의 하나입니다.
sub2 = sup2; // error! Type '{}' is missing the following properties from type 'number[]': length, pop, push, concat, and 16 more.
// sub3 타입은 sup3 타입의 서브 타입이다.
let sub3: [number, number] = [1, 2]; // Tuple 타입입니다.
let sup3: number[] = sub3;
sub3 = sup3; // error! Type 'number[]' is not assignable to type '[number, number]'. Target requires 2 element(s) but source may have fewer.
// sub4 타입은 sup4 타입의 서브 타입이다.
let sub4: number = 1;
let sup4: any = sub4;
sub4 = sup4; // any는 그 반대의 경우도 할당됩니다.
// sub5 타입은 sup5 타입의 서브 타입이다.
let sub5: never = 0 as never;
let sup5: number = sub5;
sub5 = sup5; // error! Type 'number' is not assignable to type 'never'.
class Animal {}
class Dog extends Animal {
eat() {}
}
// sub6 타입은 sup6 타입의 서브 타입이다.
let sub6: Dog = new Dog();
let sup6: Animal = sub6;
sub6 = sup6; // error! Property 'eat' is missing in type 'SubAnimal' but required in type 'SubDog'.
아래 예시에서 확인해봅니다.
// primitive type
let sub7: string = '';
let sup7: string | number = sub7;
// object - 각각의 프로퍼티가 대응하는 프로퍼티와 같거나 서브타입이어야 한다.
let sub8: { a: string; b: number } = { a: '', b: 1 };
let sup8: { a: string | number; b: number } = sub8;
// array - object 와 마찬가지
let sub9: Array<{ a: string; b: number }> = [{ a: '', b: 1 }];
let sup9: Array<{ a: string | number; b: number }> = sub9;
콜백함수의 매개변수만 반병의 규칙을 따른다고 이해하면 됩니다.
아래 예시에서 확인해봅니다.
class Person {}
class Developer extends Person {
coding() {}
}
class StartupDeveloper extends Developer {
burning() {}
}
function tellme(f: (d: Developer) => Developer) {}
// Developer => Developer 에다가 Developer => Developer 를 할당하는 경우 // 매개변수 타입이 같은 경우
tellme(function dToD(d: Developer): Developer {
return new Developer();
});
// Developer => Developer 에다가 Person => Developer 를 할당하는 경우 // 매개변수로 들어가는 인수가 슈퍼타입인 경우
tellme(function pToD(d: Person): Developer {
return new Developer();
});
// Developer => Developer 에다가 StartipDeveloper => Developer 를 할당하는 경우 // 자식 클래스인 경우
tellme(function sToD(d: StartupDeveloper): Developer {
return new Developer();
});
// 이 마지막 경우는 문제가 발생할 수 있습니다.
마지막 경우에는 문제가 발생할 수 있습니다.
왜냐하면 tellme()는 매개변수 타입인 Developer 클래스까지만 고려해서 설계되었을 텐데, Developer 클래스를 상속받은 StartupDeveloper 클래스는 Developer 클래스에는 없는 burning() 메소드를 가지고 있기 때문입니다.
하지만 TypeScript는 이부분에 대해서 사용자한테 선택권을 줍니다.

옵션을 켜지 않으면 에러가 뜨지 않습니다.