개발/이펙티브 타입스크립트

[이펙티브 타입스크립트+9] 타입 단언보다는 타입 선언을 사용

Junghyun Kim 2021. 8. 6. 00:36
반응형

https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#type-assertions

2장 타입스크립트의 타입 시스템
아이템 9 | 타입 단언보다는 타입 선언을 사용하기

3줄 요약
1. 타입 단언보다는 타입 선언을 사용하자.
2. 컴파일러보다 더 타입을 확신할 수 있을 때는 타입 단언을 사용해도 된다. 
3. 함수 시그니처를 잘 살펴보고 제너릭을 통해 리턴 타입을 정할 수 있다면 타입 단언보다 해당 방법을 더 우선으로 고려하자.

참고) 이펙티브 타입스크립트는 타입스크립트의 기본 그 이상을 다룹니다.


타입 선언과 타입 단언의 차이는 아래와 같습니다.

변수 kim에서는 타입 선언이, 변수 lee에서는 타입 단언이 사용되었습니다.

변수 kim과 변수 lee는 모두 Person 타입입니다. 그러나 타입을 부여하는 방식이 서로 다릅니다.
변수 kim에서는 타입 선언 방식이 사용되었고, 변수 lee에서는 타입 단언이 사용되었습니다.
이번 아이템에서 이야기하는 것은 타입 단언 방식 대신에 타입 선언 방식을 주로 사용하라는 것입니다.

타입 단언 방식은 강제로 타입을 지정하는 것입니다.
따라서 타입 체커에게 오류를 무시하라고 말합니다.

타입 선언 방식에서는 타입의 프로퍼티가 없으면 에러가 난다.

타입 선언 방식에서는 필요한 프로퍼티가 없으면 에러가 납니다.
그러나 타입 단언 방식에서는 에러가 나지 않습니다.

타입 선언 방식에서 다른 프로퍼티를 넣었을 때 에러가 난다.

타입 선언 방식에서는 타입의 프로퍼티 외에 다른 프로퍼티가 추가되면 에러가 납니다.
그러나 타입 단언 방식에서는 에러가 나지 않습니다.

이렇게 타입 단언을 쓰면 타입 체커의 오류를 무시하지만 그렇다고 완전히 망나니는 아닙니다.

Person의 프로퍼티의 타입과 다르면 에러가 난다.

다행히 이번에는 Person의 name의 타입과는 다른 타입이 할당되었다고 에러를 냅니다. 고맙습니다.

이러한 연유로 타입 단언보다는 타입 선언을 통해 타입을 부여하는 것을 권장합니다.
그러나, 타입 체커가 만능은 아닙니다.
가령 특정 상황에서 개발자는 특정 변수의 타입을 특정 타입이라고 확신할 수 있는 경우가 있습니다.
그러한 경우에는 타입 단언을 사용할 수 있습니다.

대표적인 예가 DOM에서 Element를 찾는 API를 사용할 때입니다.
바로 예시를 들어 보겠습니다.

querySelector로 받은 button 변수의 타입은 Element null이다.

여기서 querySelector 함수는 string을 인자로 받아서 Element | null 타입의 변수를 반환합니다.
이때, 만일 button이 HTMLButtontElement 타입이라고 개발자가 확신할 수 있다면 타입 단언을 통해서 타입을 변형해줄 수 있습니다.

타입 단언을 통한 타입 변경.

...그런데 말입니다.
이렇게 타입 단언을 하기 전에 querySelector 함수의 시그니처를 한 번 살펴보겠습니다.

querySelector 함수 시그니처.

제너릭을 사용한 부분에 관심을 가져보겠습니다. E 제너릭을 사용하는 이는 Element를 상속받습니다.
만일 E의 타입이 명시가 안된다면 기본값으로 Element를 사용합니다.
파라미터는 string 타입이고 리턴 타입은 E | null입니다.
이걸 보아하니 제너릭에 리턴받고 싶은 타입을 명시해줄 수 있는 것을 확인할 수 있습니다.

제너릭을 통한 타입 변경.

타입 단언도 가능한 옵션이긴 합니다만 이렇게 제너릭을 통한 방법이 더 깔끔해 보입니다.
함수 시그니처를 잘 살펴보고 제너릭을 통해 리턴 타입을 통제할 수 있다면 타입 단언보다는 더 안전하고 깔끔해 보입니다.

 

Materials From
1. <이펙티브 타입스크립트>(댄 밴더캄 지음, 장원호 옮김, 인사이트 2021)
2. 타입스크립트 공식 홈페이지 | https://www.typescriptlang.org/

 

Typed JavaScript at Any Scale.

TypeScript extends JavaScript by adding types to the language. TypeScript speeds up your development experience by catching errors and providing fixes before you even run your code.

www.typescriptlang.org

 


참고)
아무렇게나 as 단언을 사용할 수 있는 것은 아닙니다.
as 단언을 하려면 객체의 현재 타입이 단언될 타입의 상위 집합 혹은 부분 집합이어야 합니다.

abc의 타입과 Some 타입은 서로가 부분 집합이 아니기에 에러가 났습니다.
이럴 때는 abc 타입을 전체 집합인 unknown 타입으로 변환 후에 Some 타입으로 단언해야 합니다.
unknown 타입은 모든 타입의 상위 집합이기 때문에 가능합니다.

그러나 unknown 타입으로 단언 후에 다른 타입으로 변환하는 것은 위험합니다.
따라서 권장하지는 않습니다만 써야만 할 때에는 주의가 필요로 합니다. :)

반응형