Typescript+ReactでPropsを定義するときのTips

ReactもしくはReactNativeをTypescriptで書いていると、コンポーネントに渡すPropsを定義することは日常茶飯事です。 そんな時、知っているとちょっと便利なTipsをご紹介します。

前提条件

  • reactもしくはreact-nativeのプロジェクト
  • Typescriptを導入している

全てのプロパティをオプションにする(Partial)

がっつりコンポーネントの再利用を突き詰めていくと、割と細かい単位でコンポーネントを作成することになります。 個人的には、コンポーネントが細かくなればなるほどプロパティは必須のものが少なくなる印象です。 例えば、コンポーネントのスタイル等、親から指定したい場合とそうでない場合のもの等です。 そんな時、プロパティに?を付けてオプション化していることはないでしょうか?

type CustomButtonProps = {
  // ボタンの背景色
  bgColor? : string
  // ボタンの文字色
 color? : string
  // デバッグフラグ
  isDebug? : boolean
}

全てのプロパティをオプションにしたい場合はPartialが便利です。 下記の通り書いても、同じ結果が得られます。

type CustomButtonProps = Partial<{
  bgColor: string
  color: string
}>

union(|)

例えばstylewidthのように100"50%"のように複数の型を受けたい場合に使用します。

type CustomViewProps = {
  // stringもしくはnumberのいずれか
  width : string | number
}

intersection(&)

unionと対の存在なのがintersectionです。 複数の型の両方の性質を持たせたい場合に利用します。

type Hoge = {
  a : string
  b : number
}
type Fuga = {
  c : boolean;
  d : string | number | boolean
}

// objはHogeとFugaの両方の性質(プロパティ)を持つ
const obj : Hoge & Fuga = {
  a : '',
  b : 0,
  c : false,
  d : ''
};

プリミティブ型の値を細分化(リテラル)

プリミティブ型の中でも特にこの値だけを受け付けたい、といった場合はリテラル型がオススメです。 例えば、先のunion型と併用し、下記のように記載することでtype012しか許さない型になります。

// Hogeのtypeは0か1か2のみ許可
type Hoge = {
  type : 0 | 1 | 2
}

ちなみに先のPartialで登場した?を付けたオプションプロパティはデフォルトではundefinedです。 一見するとundefinedを複合させたunion型なのでは?と思ってしまいます。

// 下記の2通りの書き方は同じ??
type Hoge = {
  fuga? : string
}

type Puni = {
  fuga : string | undefined
}

何が違うのかというと、?の場合はfugaプロパティが存在しないことを許容しています。 string | undefinedの場合、undefinedを渡さないとなりません。

type Hoge = {
  fuga? : string
}

type Puni = {
  fuga : string | undefined
}

// これはOK
const hoge : Hoge = {}
// Property 'fuga' is missing in type '{}' but required in type 'Puni'
const puni : Puni = {}

特定のプロパティのみ抽出(Pick)

Pickで既存のtypeから特定のプロパティを抽出することができます。 既に作成したプロパティを部分的に使いまわしたい時に便利です。

// a,b,cの3つのプロパティを持つABC
type ABC = {
  a : string
  b : string
  c : string
}

// ABCからa,bを持つABを作成
type AB = Pick<ABC , 'a' | 'b'>

まとめ

ざっと紹介した限りでも、様々なPropsの定義パターンがあるように思えます。 個人的にはunionやリテラルは使用頻度が高いと思うので、覚えておいて損はないと思います。

SNSでシェアする