LoginSignup
39

More than 3 years have passed since last update.

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

Last updated at Posted at 2019-04-14

メモ書きです。

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

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

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

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

interface変更

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

変更前

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

変更後

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

onChange内で、nullの場合に関する切り分けをする

配列にアクセスする際に、nullでないことを保証します。

変更前


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

変更後

<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://github.com/Microsoft/TypeScript/issues/14889#issuecomment-289613908

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

まとめ

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


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)

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
39