TypeScriptで "Object is possibly null" と怒られたときにすること

メモ書きです。

https://github.com/Microsoft/TypeScript/issues/14889
参考にしたIssue

例えば、画像をアップするところをやっていて、次のようなコンポーネントを扱っているとします。
(適当にそれっぽい雰囲気にしています)

```jsx
import * as React from 'react'
import { compose, pure } from 'recompose'
import Icon, { IconType } from '../../atoms/Icon/Icon'
import * as styles from './ImageUploader.css'

interface ImageUploaderProps {
  onChangeImage: (data: any) => void
}

const ImageUploader: React.FunctionComponent<ImageUploaderProps> = ({ onChangeImage }) => {
  return (
    <div className={styles.container}>
      <label className={styles.buttonLabel}>
        <span>
          <Icon iconType={IconType.IMAGE_UPLOAD_ICON} />
          アップロード
        </span>
        <input
          hidden
          id={'file_image'}
          type="file"
          accept="image/png,image/jpg,image/bmp"
          onChange={e =>
            onChangeImage(targetImage: e.target.files[0])
          }
        />
      </label>
    </div>
  )
}

export default compose<ImageUploaderProps, ImageUploaderProps>(pure)(ImageUploader)
```

inputに画像をアップする際、そこからFileオブジェクトを抜き出すときは `files` に配列で格納されているのでこれをindex指定で取り出す必要があります。

しかし、上のコードはこのままだとエラーが出ます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109201/4c38b347-cbf0-4894-9152-edfda84c81c0.png)

nullかもしれないオブジェクトに対する操作は認められない、という感じですね。では、nullじゃないことを保証すればよいわけです。ここでは2つ変更します。

## interface変更
まずinterfaceが雑に `any` を使ってしまっているのでこれを直しましょう。

### 変更前
```typescript
interface ImageUploaderProps {
  onChangeImage: (data: any) => void
}
```

### 変更後
```typescript
interface ImageUploaderProps {
  onChangeImage: (object: { targetImage: File | null }) => void
}
```

## onChange内で、nullの場合に関する切り分けをする
配列にアクセスする際に、nullでないことを保証します。

### 変更前
```jsx

<input
  hidden
  id={'file_image'}
  type="file"
  accept="image/png,image/jpg,image/bmp"
  onChange={e =>
    onChangeImage(targetImage: e.target.files[0])
  }
/>
```

### 変更後
```jsx
<input
  hidden
  id={'file_image'}
  type="file"
  accept="image/png,image/jpg,image/bmp"
  onChange={e =>
    onChangeImage(targetImage: e.target.files !== null ? e.target.files[0] : null)
  }
/>
```

参考にしたIssueでは、guard文で早めに抜けていました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109201/533e0059-7118-385c-7178-9fa694847adf.png)
https://github.com/Microsoft/TypeScript/issues/14889#issuecomment-289613908

しかし、onChangeの関数内で同様に抜けようとするよりも、三項演算子でnullを回避するほうが見やすいかと思ってこのように書いています。
nullが裏のsagaなどに行ってしまうので、そこでの制御はどちらにせよ必要ですね...

## まとめ
最終的には以下のようになります。

```jsx

import * as React from 'react'
import { compose, pure } from 'recompose'
import Icon, { IconType } from '../../atoms/Icon/Icon'
import * as styles from './ImageUploader.css'

interface ImageUploaderProps {
  onChangeImage: (object: { targetImage: File | null }) => void
}

const ImageUploader: React.FunctionComponent<ImageUploaderProps> = ({ onChangeImage }) => {
  return (
    <div className={styles.container}>
      <label className={styles.buttonLabel}>
        <span>
          <Icon iconType={IconType.IMAGE_UPLOAD_ICON} />
          アップロード
        </span>
        <input
          hidden
          id={'file_image'}
          type="file"
          accept="image/png,image/jpg,image/bmp"
          onChange={e =>
            onChangeImage(targetImage: e.target.files !== null ? e.target.files[0] : null )
          }
        />
      </label>
    </div>
  )
}

export default compose<ImageUploaderProps, ImageUploaderProps>(pure)(ImageUploader)
```