보통 타입스크립트는 자바스크립트의 상위호환이다 라고 합니다.
즉 모든 자바스크립트는 타입스크립트이지만 반대로 모든타입스크립트가 자바스크립트는 아닙니다.
타입스크립트는 별도의 문법을 가지고 있기 때문입니다.
단 우리가 처음에 헷갈리는 이유는 우리가 작성하는 코드는 자바스크립트이면서 타입체커를 통과한 코드이기 때문에 오히려 타입스크립트가 자바스크립트 안에 있는 것처럼 생각한 것입니다.
typescript->javascript로 변환을 하는 행동과 타입을 체크하는 행동은 서로 관련이 없습니다.
만약 타입에 오류가 생긴다 해도 컴파일은 완료가 될 수 있습니다.
즉 우리가 타입스크립트를 이용하다 오류가 나온 것이면 컴파일에러보단 타입에러가 일어났다고 표현하는 것이 좀 더 맞습니다.
왜냐하면 컴파일은 잘 작동하기 때문입니다.
자바스크립트는 본질적으로 덕타이핑 기반입니다.
타입스크립트 또한 자바스크립트를 모델링 하므로 덕타이핑을 기반으로 합니다
interface People{
name:string
age:number
}
const Hello =(people:People)=>{
return `${people.name} and ${people.age}`
}
const My : People={
name: "an",
age:20
}
console.log(Hello(My)) // an and 20이 나온다.
interface You {
name: string,
age:number,
food:string
}
const Your:You = {
name: "kim",
age:20,
food:"apple"
}
console.log(Hello(Your)) // kim and 20이 나온다
분명 밑에 You에 인자가 하나 더 있는데도 멀쩡하게 작동이 됩니다.
이유는 You가 People의 인자를 모두 가지고 있기 때문입니다.
즉 같은 형태의 인자를 가지고 있어 호환이 가능해졌습니다.
우리가 정한 타입만 들어 갈 것이라 생각하지만, 실제로는 정해진 타입만 들어가는 것이 아니기에 타입이 열려있다라고 표현을 합니다.
또한 타입체크는 덕 타이핑으로 일어나는 것을 에러라고 하지 않습니다.
위에서 타입스크립트는 자바스크립트를 모델링한 다라고 했는데, 즉 타입스크립트는 동적 다형성을 지니게됩니다.
정적 다형성은 컴파일 시점 바인딩을 의미하며, 동적 다형성은 런타임 시점 바인딩을 의미합니다.
객체 지향 언어에서 정적 다형성은 overloading, 동적 다형성은 overriding이라 하는데,
정적 다형성(overloading)은 동일한 함수 이름을 가지더라도 해당 함수가 가지는 파라
미터들의 개수, 타입, 순서가 다를 경우 컴파일러가 다른 함수로 인식하는 반면,
동적 다형성(overriding)은 동일한 함수 이름과 파라미터 특성을 지닌, 상속 관계에
있는 클래스들의 멤버 함수에 대해서 외형적으로 호출되는 타입에 상관없이 실제 생성된 객체의 함수가 호출되도록 처리되는 특성입니다
이 중에 덕 타이핑이 해당되는 파트는 동적 다형성으로 보입니다.
타입을 집합의 관점에서 바라보기
추가적으로 집합에 대한 시각으로 볼 때 유니온타입과 구조적타입이 다릅니다.
keyof (A&B) = (keyof A) | (keyof B) //구조적 타입
keyof (A|B) = (keyof A) & (keyof B) //유니온타입
자세히 살펴봅시다.
1.구조적 타입에서의 교집합이란?
interface A {
name: string
}
interface B {
age: number
gender: string
}
이라는 타입이 2개있을 때
각각
const AB = A & B
const CD = key of(C|D)
라고 할 때 과연 둘의 값이 어떻게 나올까요?
interface AB {
name: string
age: number
gender: string
}
interface CD 는 never가 나옵니다
왜 이런일이 일어날까요?
const AB = A & B에서 &는 교집합이라 공통된 것을 가져와야 할 것 같지만 구조적타이핑에 따르면 AB가 A 와 B의 타입에도 속해야 한다는 뜻입니다.
즉 A와B의 속성들을 다 가지면 문제가 양쪽의 타입을 갖게 되어 오류가 나오지 않습니다.
그래서 &는 공통된 것을 찾는 것이 아닌 구조적타이핑에 의해 두 타입의 모든 것을 포함한 타입이 나오게됩니다
이것이 타입관점에서의 교집합입니다.
const CD는 위와 반대로 never가 나옵니다.
이유는 어떤 타입이 A에 속하거나 B에 속해야한다는 뜻인데 위에 예시에서는 두개의 타입이 될 수 있는 속성이 아무것도 없습니다.
그래서 never가 나오게 됩니다.
만약 타입가드를 쓴다면 하나의 타입만 이용하기에 상관이 없지만 만약 그대로 유니온타입만을 쓴다면 함수는 어느타입이 들어올 지 알 수없어 공통된 것만을 가져와 오류가 안나오도록 하는 것입니다.
결론적으로 이렇게 되는 이유는 자바스크립트의 구조적 타이핑을 타입스크립트가 모델링했기 때문입니다.
또한 이러한 이유로 유니온 타입에서는 extneds를 사용할 수 없습니다.
interface Vector1D { x: number; }
interface Vector2D { x: number; y: number; }
interface Vector3D { x: number; y: number; z: number; }
는
interface Vector1D { x: number; }
interface Vector2D extends Vector1D { y: number; }
interface Vector3D extends Vector2D { z: number; }
와 같습니다
원을 그려보면 가장 위에 vector1이 있고 그 밑에 vector2 vector3가 있는 것입니다 왜냐하면 vector1안에는 여러가지 속성들이 있을 수 있고 vector1만 만족시키면 추가적인 속성을 가져도 vector1에 해당하기 때문입니다.
참고자료
https://velog.io/@yena1025/%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EB%8D%95-%ED%83%80%EC%9D%B4%ED%95%91-%EA%B5%AC%EC%A1%B0%EC%A0%81-%ED%83%80%EC%9D%B4%ED%95%91
http://blog.hwahae.co.kr/all/tech/tech-tech/9954/