[ts] 타입호환성

타입호환성

타입스크립트는 Structural typing에 기반을 두고 있다. 즉, type이라는 것은 해당 타입의 멤버를 보고 타입을 결정한다는 것이다,

아래와 같이 Human class가 Person을 구현하지 않음에도 불구하고 멤버가 같기 때문에, 타입 호환이 가능하다.

interface Person {
	name: strng;
}
class Human {
	name: string
}

let p: Person;
p = new Human(); // 문제 없음

타입 호환성이라는 것은 다른 언어에서 있는 것인데, 아래와 같이 int + double과 같은 연산이 가능한 것과 같은 것이다.

	double sum = 4 + 4.2;

즉, 타입스크립트는 Structural typing을 기반으로 타입 호환성을 검사하기 때문에,

const a: typeA = b: typeB;
  1. A에 있는 모든 필수 속성의 이름이 B에도 존재한다.
  2. 같은 속성 이름에 대해, B의 속성이 A의 속성에 할당 가능해야 한다.
interface Named {
  name: string;
}

let x: Named;
// y's inferred type is { name: string; location: string; }
let y = { name: "Alice", location: "Seattle" };
x = y;
x.location // 이 경우 Named type에는 location이 없기 때문에 컴파일 에러. 그런데 typscript playground에서는 된다..

위와 같은 경우에 Named 라는 타입이 y의 객체 타입보다 더 포괄적인 타입이다. 이때, x의 멤버를 y가 모두 가지고만 있으면, 타입 호환이 되는 것이다.

function func1(a: number, b: number | string) {
	const v1: number | string = a;
	const v2: number = b; // error
}
function func2(a: 1 | 2) {
	const v1: 1 | 3 = a; // error
	const v2: 1 | 2 | 3 = b;
}

더 큰 범위의 타입에 작은 범위의 타입이 할당 될 수 있다.(추가적인 제약이 맞아야한다)

Optional 프로퍼티는 일반 속성보다 큰 범위를 가진다.

interface Person {
	name: string;
	age? :number;
}
interface Friend {
	name: string;
	age: number;
}
const obj = { name: 'pius' };

const person: Person = obj;
const friend: Friend = obj;

함수의 타입 호환성

함수 타입 B가 함수 타입 A에 할당 가능하기 위한 조건.

  1. B의 매개변수 개수가 A의 매개 변수 개수보다 적어야 한다.
  2. 같은 위치의 매개변수에 대해 A의 매개변수가 B의 의 매개변수로 할당 가능해야한다.
  3. B의 반환값은 A의 반환값으로 할당 가능해야 한다.
type F1 = (a: number, b: string) => string;
type F2 = (a: number, b: string | number) => string;
type F3 = (a: number) => string;
type F4 = (a: number) => number | string;

let f1: F1 = (a, b) => `${a} ${b.length}`;  
let f2: F2 = (a, b) => `${a} ${b}`;
let f3: F3 = a => `${a}`;
let f4: F4 = a => (a < 10? a: 'nono');

f1 = f3;
f3 = f1; // error
//


f1 = f2;
f2 = f1; // error
// F2의 두번째 인자는 string | number 이기 때문에
// F1의 두번째 인자 string에 할당 불가능

f4 = f3;
f3 = f4; // eeror
f3(1).length

#타입스크립트/타입-호환성