TypeScript if と switch のどちらを使うかの一つのポイント

TypeScript で if と swtich のどちらを使うかの一つのポイントについて紹介です。

前提として、以下があるとします。

  • ある関数があり、その関数の引数にユニオン型を受け取る
  • 関数内ではユニオン型の絞り込みを行うために条件分岐をする

具体例です。

type Employee = {
    type: 'employee'
    employeeNum: number,
    name: string
}

type Customer = {
    type: 'customer'
    customerId: number,
    name: string
}

type User = Employee | Customer

const getEmployeeNumWithIf = (user: User): number | undefined => {
    if(user.type === 'employee'){
        return user.employeeNum
    }else{
        return undefined
    }
}

const getEmployeeNumWithSwitch = (user: User): number | undefined => {
   switch(user.type){
       case 'employee': {
           return user.employeeNum
       }
       case 'customer': {
           return undefined
       }
   }
}

getEmployeeNumWithIf と getEmployeeNumWithSwitch 関数は User 型を受け取ります。

この User 型は Employee | Customer というユニオン型です。

そして、関数内では、Employee なのか Customer なのかによって分岐しています。

両者ともに同じ処理をしていますが、ある条件の場合に switch 文の方にメリットが生じます。

それは、ユニオン型に変更(追加)があった際に、関数内を変更することに気づける点です。

type Employee = {
    type: 'employee'
    employeeNum: number
    name: string
}

type Customer = {
    type: 'customer'
    customerId: number
    name: string
}

type SpecialUser = {
    type: 'special',
    specialId: number
    name: string
}

type User = Employee | Customer | SpecialUser

const getemployeeNumWithIf = (user: User): number | undefined => {
    if(user.type === 'employee'){
        return user.employeeNum
    }else{
        return undefined
    }
}

// Not all code paths return a value. というエラーになる
const getemployeeNumWithSwitch = (user: User): number | undefined => {
   switch(user.type){
       case 'employee': {
           return user.employeeNum
       }
       case 'customer': {
           return undefined
       }
   }
}

User 型に SpecialUser という型が追加されました。

getemployeeNumWithIf はコンパイルエラーにはなりませんが、getemployeeNumWithSwitch はコンパイルエラーになります。

これによって、case 'special’ を追加しなくてはいけないことが開発者に分かります。

このように switch を使えば、型の追加によって変更が必要な個所を知ることができます。

このように TypeScript は switch 文の case が網羅的になっているかをチェックしてくれます。