[240104] Assertion functions in TypeScript

Assertion functions in TypeScript

NodeJs 에서는?

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 를 통해 타입 단언을 시킨 뒤 반환 값을 강제할 수 있다.

TypeScript 에서는?

  • 타입 스크립트에서도 assertion signatures 도입

Why?

let name: null | string = "홍길동"

function whatIsNameType() {
  name // null | string

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

  name // string
}

if (name != null) {
  whatIsNameType()
}
  • 느슨한 타입 검사 방식으로 부분적으로 타입 보장이 안된다.
  • whatIsNameType 함수 실행하는 조건은 namenull이 아닐 때 인데, 막상 함수 내부에서는 null 과 string 타입 두개이다.
const person = {
  name: "홍길동",
  age: 13,
}

function check<T>(obj: T): obj is T & { check: boolean } {
  ;(obj as T & { check: boolean }).check = true
  return true
}

if (check(person)) {
  person.check // check OK
}

person.check // type error
  • 개발 진행중인 person 객체가 있는데, check 를 넣어주고 싶은 상황
  • 위 처럼 유형 가드로 해주면 타입 단언과 유사하긴 하지만 매번 if 문으로 분기처리를 해줘야함.
function check<T>(obj: T): asserts obj is T & { check: boolean } {
  ;(obj as T & { check: boolean }).check = true
}

check(person)
console.log(person.check)

그 외 만들어본 예시

function assertNumber(val: any): asserts val is number {
  if (typeof val !== "number") {
    throw new Error("val is not number")
  }
}

function assertString(val: any): asserts val is string {
  if (typeof val !== "string") {
    throw new Error("val is not string")
  }
}

function sum(x: unknown, y: unknown) {
  assertNumber(x)
  assertNumber(y)
  //assertString(x) 한번 더 사용하면 x 타입은 never이 된다.

  return x + y
}

console.log(sum(2, 3)) // output 5
// 하나의 assertions 함수를 만들어서 타입 단언 가능
function assertions(condition: any, msg?: string): asserts condition {
  if (!condition) {
    throw new Error(msg)
  }
}

const hello: any = "2"

assertions(typeof hello === "number", "number no")

console.log(hello) // hello 타입은 number가 된다.

Categories:

Updated:

Leave a comment