타입스크립트의 Assertion Functions을 활용해 타입 보장하기

2022. 5. 7

타입스크립트를 활용해 개발하다 보면 기존 자바스크립트만으로 개발할 때보다 안정성이 확실히 증가하는 것을 느낀다.

컴파일 단계와 타입체킹 단계에서 타입스크립트 엔진이 어련히 알아서 타입 추론과 체크를 해주는 덕분에 우리는 타입스크립트가 시키는대로 조건만 맞추어 준다면 편안- 하게 개발이 가능하다. (물론 불편한 점들도 있지만.. 😇)

하지만 타입스크립트의 타입에도 허점이 있다. 바로 부분적으로 타입 보장이 안된다는 것이다.

예를 들어보자!

재미난 현상 발견

let nickname: null | string = 'fronttigger'

function whatIsNicknameType() {
  nickname // null | string

  if (nickname == null) {
    nickname // null
    return
  }

  nickname // string
}

if (nickname != null) {
  whatIsNicknameType()
}

위 코드를 보면 뭔가 쎄하다. 🤔

분명 whatIsNicknameType 함수를 실행하는 조건은 nickname 변수가 null이 아닐 때 인데, 막상 함수 내부에서의 첫 번째 nickname은 null과 string 타입 두 개의 타입이다.

뭔가 이상하지 않은가?

바로 이런 부분에서 타입스크립트는 느슨하게 타입을 검사한다.

이를 방지하기 위해 Node.js 에서는 assert 라는 함수를 사용한다.

Node.js 에서는?

const assert = require('assert')

function multiply(x, y) {
  assert(typeof x === 'number')
  assert(typeof y === 'number')

  return x * y // number * number
}

multiply(2, 2) // 4
multiply(3, '1')
// AssertionError [ERR_ASSERTION]: The expression evaluated to a falsy value: assert(typeof y === 'number')

assert를 통해 특정 타입을 단언을 시킨 후 반환 값을 강제했다.

만약 단언한 값이 들어오지 않을 경우 AssertionError를 던져낸다.

이에 관한 사항은 타입스크립트 3.7에 공식적으로 명시가 되어있다.

그래서 타입스크립트는 위와 같은 현상을 해결하기 위해 assertion signatures를 도입하였고 이를 통해 Node.js에서 사용하던 방식처럼 사용이 가능하다.

한 번 만들어보자!

assert function 구현

export default function assert(condition: unknown, errorMessage?: string): asserts condition {
  if (!condition) {
    throw new Error(errorMessage || 'condition 조건이 true가 아닙니다.')
  }
}

함수의 타입에 asserts 키워드가 들어갔다.

그리고 asserts는 타입을 보장하기 위한 인자를 가진다. (여기서는 condition)

이렇게 되면 입력받은 condition이 true인 경우 조건이 포함하는 범위의 나머지 부분에 대한 타입을 보장받는다.

assert function 사용

function getNickname(name: string | null): string {
  assert(name != null) // true

  return name // string
}

getNickname('fronttigger') // fronttigger

위에서 만든 assert 함수를 사용한 간단한 함수를 만들어보았다.

여기서 name 인자로 넘어온 값이 'fronttigger' 문자열이므로 true가 되어 Error을 throw 하지 않는다.

원래는 내부에서 느슨한 타입체크로 인해 null 확인을 추가로 해줘야하는 번거로움이 있었지만, 이제 그럴 필요 없이 assert 함수를 true 조건으로만 맞추어준다면 그 다음 부터는 true에 대한 타입이 보장받게 된다. 👍

이런 타입 가드 함수들을 통해 보다 안전하고 깔끔한 타입스크립트 코딩이 가능하다! 💻