음악, 삶, 개발
Typescript Type 시스템 이해하기 : Structural Typing 본문
https://velog.io/@vlwkaos/Structural-vs-Nominal-Subtyping-그리고-TypeScript
https://michalzalecki.com/nominal-typing-in-typescript/
C++ 같은 경우 클래스 이름으로 타입을 결정하는 nominal typing 이다.
반면 Typescript 는 클래스의 내부 구조가 동일할시
동일한 타입으로 인식하는 strutual typing 을 사용한다.
class A { name = "hello" }
class B { name = "world" }
const foo: A = new B () // ok
클래스 A 를 extends 하여 클래스 B 를 만들어도 내부 구조가 같이 때문에,
동일한 타입으로 인식이 된다.
class A { name = "hello" }
class B extends A {}
const foo: A = new B () // ok
특히 extends 를 한 경우에 클래스 B 에 다른 property 들이 추가 되더라도,
base 클래스가 같은 이상 동일한 타입으로 인식한다.
private member 가 생기든 말든 아무리 뭘 추가해도 base 가 같으면 같은 클래스이다.
class A { name = "hello" }
class B extends A {
private unique = "unique"
one = "one"
two = "two"
three = "thre"
}
const foo: A = new B () // ok
하지만 때에 따라서 extends 된 class 들 서로를 구분하고싶을수있다.
이때 자식 class 에 private 멤버를 하나 추가하면
nominal typing 을 흉내(?) 낼수있다.
class Base { }
class ChildA extends Base {
private _nominalTypePlaceHolder: any
}
class ChildB extends Base {
private _nominalTypePlaceHolder: any
}
const a: ChildA = new Base ()
// Property '_nominalTypePlaceHolder' is missing in type 'Base' but required in type 'ChildA'
const a: ChildA = new ChildB ()
// type 'ChildB' is not assignable to type 'ChildA'.
// Types have separate declarations of a private property '_nominalTypePlaceHolder'
이때 중요한건 ChildA 와 ChildB 둘다 private 멤버가 있어야한다.
그리고 private 멤버에 아무것도 대입하지않는한 JS 로 컴파일후 런타임에서 저 변수는 실제로 존재하지않는다.