음악, 삶, 개발

Typescript Type 시스템 이해하기 : Structural Typing 본문

개발 Web/TypeScript

Typescript Type 시스템 이해하기 : Structural Typing

Lee_____ 2022. 3. 14. 22:53

https://velog.io/@vlwkaos/Structural-vs-Nominal-Subtyping-그리고-TypeScript

https://michalzalecki.com/nominal-typing-in-typescript/

https://stackoverflow.com/questions/26810574/is-there-a-way-to-create-nominal-types-in-typescript-that-extend-primitive-types

 

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 로 컴파일후 런타임에서 저 변수는 실제로 존재하지않는다.