Typescript+ReactでDefault parametersにObjectを正しく設定する方法

最近、React+Typescriptしか書いてないので、久々に小ネタを投下しようかなっと。。。

tl;dr

  • JavaScriptでよくやる引数の object = object || {} を、Typescriptでコンパイルエラーを回避しながらどうやるか。

ユースケース

例えば、Reactでこのようなstateless function components(以下、Book)を作ったとします。
Bookはインタフェースとして、bookを受け取ってnameを表示する非常に単純なcomponentです。

1
2
3
4
5
6
7
8
9
10
11
interface IBook {
name: string;
}

interface IBookProps {
book: IBook;
}

export defaut function Book({ book }: IBookProps) {
return <div>{book.name}</div>
};

ところが、 bookはAPIから取得する必要があり、Bookを初期化されるタイミングではundefinedとなっています。

おそらく、bookundefinedのまま、Bookに渡した場合は、次のようなエラーが発生するでしょう。

1
Uncaught TypeError: Cannot read property 'name' of undefined

ES6 Default parameters を使ってみる

早速、book = book || {}と行きたいのですが、ES6のDefault parametersを使ってみます。

1
2
3
export defaut function Book({ book = {} }: IBookProps) {
return <div>{book.name}</div>
};

しかし今度は、 IBook型と一致しないというコンパイルエラーが出力されます。

1
error TS2322: Type '{}' is not assignable to type 'IBook'. Property 'name' is missing in type '{}'.

まぁ、当然ですね。

正しいDefault parametersの使い方

{}には型を設定することができるので、Default parametersを設定するときに正しく型を指定してみます。
これで、コンパイルエラーを無事回避することができました。さらにIDEの補完も効きます。

1
2
3
export defaut function Book({ book = {} as IBook }: IBookProps) {
return <div>{book.name}</div>
};

まとめ

最初は、IBookを実装した、クラスを定義してダミーの値を設定しないと無理かと思っていましたが、型を設定することであっさり出来ました。

Typescriptのintarfaceは定義するの少し面倒ですが、こういう場合に重宝するので、定義した方がいいですよー。