TypeScript オブジェクトのリテラルを推論する場合はタグをつけると良い

以下のコードは、 T2 に hoge プロパティが存在しない、というエラーになります。

type T1 = {
    hoge: string
}
type T2 = {
    foo: number
}


const myFunc = (value: T1 | T2) => {
    if(value.hoge !== undefined) {
        value
    }else{
        value
    }
}

一見すると、hoge が undefined になるのは T2 なので、value.hoge !== undefined の if のブロック内のvalueはT2だと推論してくれそうですが、TypeScripはしてくれません。

実は以下のようにT1に対してhogeとfooの両方をもつオブジェクトを割り当てることが可能なためです。(bに直接代入する場合は過剰プロパティチェックが働くためエラーになる)

const a = {
    foo: 100,
    hoge: 'hoge'
}

const b: T1 = a

こういう場合に困った時は、タグをつけた型を定義すると良いです。

type T1 = {
    type: 'hoge'
    hoge: string
}
type T2 = {
    type: 'foo'
    foo: number
}


const myFunc = (value: T1 | T2) => {
    if(value.type === 'hoge') {
        value //T1
    }else{
        value //T2
    }
}