TypeScript2からのReactとnon-null assertion

TypeScript2からコンパイルオプションの strictNullChecks で、nullability をチェックできるようになった。
最近になってこのオプションを有効にしたら意外と修正するところが多かったのでメモ。

TypeScript1系の時は↓の様に書いてました。

import * as React from 'react'
import * as ReactDom from 'react-dom'

interface IAProps {
}
interface IAState {
  hoge?: string;
  fuga?: number;
}
class A extends React.Component<IAProps, IAState> {
  constructor(props: IAProps) {
    super(props);

    this.state = {
      hoge: '',
      fuga: 0
    }
  }

  render() {
    return(
      <B
        hoge={this.state.hoge}
        fuga={this.state.fuga}
      />
    );
  }
}

interface IBProps {
  hoge: string;
  fuga: number;
}
interface IBState {
}
class B extends React.Component<IBProps, IBState> {
  constructor(props: IBProps) {
    super(props);

    this.state = {
    }
  }

  render() {
    return(
      <div>
        {this.props.hoge}
        <br />
        {this.props.fuga}
      </div>
    );
  }
}

TypeScriptでstate管理するときは、毎回全部のパラメータを更新したいわけではないので

interface IAState {
  hoge?: string;
  fuga?: number;
}

という感じに? を付けてオプショナルにしていました。

そうすると、stateで管理しているhoge fugaの型が

hoge: string | undefined
fuga: number | undefined

と、それぞれ undefined になる可能性があるということになる。

Component B に値を渡すとき、Component B側では

interface IBProps {
  hoge: string;
  fuga: number;
}

というようにundefinedは許容されないので、

  render() {
    return(
      <B
        hoge={this.state.hoge!}
        fuga={this.state.fuga!}
      />
    );

!を付けて、non-nullであることを明示してあげないといけない。

最終的にソースコードはこうなりました。

import * as React from 'react'
import * as ReactDom from 'react-dom'

interface IAProps {
}
interface IAState {
  hoge?: string;
  fuga?: number;
}
class A extends React.Component<IAProps, IAState> {
  constructor(props: IAProps) {
    super(props);

    this.state = {
      hoge: '',
      fuga: 0
    }
  }

  render() {
    return(
      <B
        hoge={this.state.hoge!}
        fuga={this.state.fuga!}
      />
    );
  }
}

interface IBProps {
  hoge: string;
  fuga: number;
}
interface IBState {
}
class B extends React.Component<IBProps, IBState> {
  constructor(props: IBProps) {
    super(props);

    this.state = {
    }
  }

  render() {
    return(
      <div>
        {this.props.hoge}
        <br />
        {this.props.fuga}
      </div>
    );
  }
}

参考

15K 行のアプリを TypeScript 1.8 から 2.0 に移行してみた - はやくプログラムになりたい