deve.K

エンジニアが未来を切り開く。

Typescriptで学ぶReact 入門 propsの渡し方と定義

reactとtypescript

記念すべき当ブログの100記事目の投稿として、TypeScriptとReactの入門を初学者様に解説していきます。

当記事のチュートリアルでは、create-react-app (CRA) を使って、TypeScriptを使用したReact アプリケーションの構築を、設定不要ですぐに始める方法とTypeScriptを使用した独自のReact関数コンポーネントでのpropsの定義方法の解説となります。

state(状態)管理につきましては別途、他の記事で解説致します。

※ Node.jsとnpmはすでにあなたのマシンにインストールされていると仮定します。

※ 事前にTypeScriptの基本的な基礎に精通してる必要があります。

TypeScriptで学ぶReact入門となります。

TypeScriptについては下記で解説しております

dev-k.hatenablog.com

TypeScriptとReactの利点

これはReactアプリを構築するための比較的新しい方法です。

TypeScriptは、型付き構文をサポートするJavaScriptのスーパーセットです。

ブラウザが実行できるようにプレーンなJavaScriptコンパイルします。

TypeScriptは一般的に、読みやすさと型チェックが主な理由で、フロントエンドWeb開発でますます人気が高まっています。

TypeScriptの静的型システムは、問題を早期に発見するのに役立ちます。

たとえば、コンポーネントを参照するときに必要なpropsを提供していない場合、TypeScriptコンパイラはこれを検出して報告します。

VSコードを使用してる場合、赤い波線でこれをすぐに指摘してくれます。

TypeScriptとReactは完璧にジャストフィットします。

両方のテクノロジーを組み合わせて、アプリケーションを作成する際の生産性を大幅に向上させることができます。

より、クリーンなコードで間違いなくバグが少なく、さらによりシンプルなドキュメントです。

最も明白で影響力のあるものは、開発者がコードを保守しやすくなり、コンポーネント間で渡されるプロパティとデータ型をチェックすることでバグを防ぎ、実装の意図をはるかに明確にする事になります。

TypeScriptはすべての大規模なReactプロジェクトにとって価値のあるオプションであることがわかります。

CRAのインストール

create-react-app(CRA)は、webpackやbabelなどを気にすることなく、デフォルトとゼロ構成で新しいReactアプリを作成し、簡単に開発を開始できるためのコマンドライン(CLI)ツールです。

npm install -g create-react-app

TypeScriptは次のステップで、『 npx 』を使用してインストールが可能です。

コードエディタはVSCodeをお勧めします。

それは軽量で高速であり、必要なすべての機能を提供するためです。

ですが、SublimeText、WebStorm、Atomなどの他のものを使用したい場合は、自由に選択してもらって構いません。

この記事ではエディタは関係ありません。

TypeScriptでReactアプリを初期化

create-react-appコマンドに TypeScriptオプションを追加して起動すると、デフォルトのJS構文として TypeScriptを使用した、React アプリケーションが生成されます。

npx create-react-app my-app --template typescript

npxはnpm 5.2でリリースされたコマンドで、CLIコマンドやレジストリにホストされている実行ファイルを実行することができます。

そのため、グローバルインストールはもはや必要ありません。

一度でもCRAを使用した事のある方でしたら、見慣れていると思いますが、追加情報は--template typescriptフラグを追加することです。

このフラグは、CRAにTypeScriptをデフォルトの構文として使用するように指示し、箱から出して動作させるために適切な設定を追加します。

※ Create React Appの以前のバージョンでは、--typescriptフラグを使用できましたが、このオプションは廃止されました。

インストールが完了すると、TypeScriptをサポートする新しいReactアプリケーションが作成されます。

プロジェクトディレクトリに移動し、コードエディタで開きます。

下記のようなファイルとフォルダ構成が生成されます。

CRAのバージョンの違いにより、階層構造は前後する、または大きく異なる可能性があります。

my-app/
├─ node_modules/
├─ public/
    | — favicon.ico
    | — index.html
    | — logo192.png
    | — logo512.png
    | — manifest.json
    | — robots.txt
├─ src/
    | — App.css
    | — App.test.tsx
    | — App.tsx
    | — index.css
    | — index.tsx 
    | — logo.svg
    | — react-app-env.d.ts
    | — reportWebVitals.ts
    | — setupTests.ts
    | — registerServiceWorker.ts
├─ .gitignore
├─ package.lock.json
├─ package.json
├─ README.md
└─ tsconfig.json

tsconfig.json

tsconfig.jsonファイルは、JavaScriptプロジェクトのpackage.jsonと同様に、TypeScriptプロジェクトのコンパイラ設定とファイルを示す設定ファイルとなります。

{
  "compilerOptions": {
    "target": "es5",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noFallthroughCasesInSwitch": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx"
  },
  "include": [
    "src"
  ]
}

その中でも『"target": "es5"』では、古いブラウザとの互換性を高めるために、targetで対応したいECMA Scriptのバージョン指定となっています。

JSXには.tsxファイルを使用

TypeScriptでReactを使用するには、標準のReactアプリの作成方法に少し変更を加える必要があります。

TypeScript用の新しい.tsファイルに加えて、さらに新しいファイル拡張子.tsxもあります。

これは、ReactコンポーネントファイルにJSX構文を含めるときはいつでも使用すべき拡張子となります。

TypeScriptは、JSXを直接JavaScriptコンパイルすることができます。

TypeScriptを使用していく上で最も優れている点の1つは、パッケージを使用する必要がなくなったことです。

propsとstateにTypeScriptを使用することには少し学習曲線がございますが、一度理解してしまえば、Reactのデフォルトの方法よりもはるかに強力となっています。

TypeScriptコンポーネント作成

まずは、デフォルトのApp.tsxファイル開いてみましょう。

import React from 'react';
import logo from './logo.svg';
import './App.css';

function App() {
  return (
<div className="App">
  <header className="App-header">
    <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.tsx</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
>
          Learn React
        </a>
      </header>
    </div>
  );
}

export default App;

imgタグとaタグ、そしてロゴなどのインポートは必要ないので下記のようにします。

function App() {
  return (
<div className="App">
  <header className="App-header">

  </header>
</div>
  );
}

export default App;

ではこのまま、App.tsxファイル内に関数コンポーネントを作成していきます。

まずは、propsの流れを掴んでいきましょう。

TypeScriptを使用しないコンポーネントの違いを示す簡単な例を次に示します

下記ではAppコンポーネントが親となり、Childコンポーネントが子の関数コンポーネントとなります。

userというオブジェクトと、Numを作る関数、そして2つの変数の値を宣言しています。

コンポーネントレンダリングの一部としてコンポーネントの子を宣言し、Child属性(HTML属性の有効な名前)を割り当てます。

これはすべて変数に等しくなります、関数はpropsとして送信します。

// Appコンポーネント

function App() {
  const user = { age: 30, name: "Taro" }

  const funcNum = num => {
    return num + 2
  }
  const title = "Hello!!, React with TypeScript."
  const content = "propsを送ります"
  return (
    <div>
      <Child
        title={title}
        content={content}
        user={user}
        num={funcNum}
      />
    </div>
  )
}

子の関数コンポーネントは、最初の引数としてpropsをオブジェクトとして受け取り、親コンポーネントで属性として設定された、オブジェクトのプロパティの各名前は、子コンポーネントのpropsの名前となります。

一般的な方法では、これら受け取ったオブジェクトを分解することです。

// Child コンポーネント

export default function Child({ title, content, user, num }) {

  console.log(num(3)) // 5

  return (
    <div>
      <h2>{title}</h2>
      <p>{content}</p>
      <p>{user.age}</p>
      <p>{user.name}</p>
    </div>
  )
}

See the Pen React with Typescript interface 拡張 by dev.K | Webアプリ開発者 (@enjinia_f) on CodePen.


それでは、ReactでTypeScriptを使用して関数コンポーネントを作成するときに、propsの型チェックを実行する方法を見ていきます。

型の定義で子に渡していきます。

MyMessageという子の関数コンポーネントを作成します。

const MyMessage = ( ) => {
  return <div><h2>Welcome to the {message} of React and TypeScript.</h2></div>;
}

全てのpropsに対して、オブジェクトとして型を定義をしなければいけません。

TypeScriptは型に厳しいJavaScriptライブラリなので、React propsの型を定義する必要があり、型を宣言する方法は様々です。

その型の宣言の実現する方法をいくつかを学んでみましょう。

propsの渡し方

インラインで定義

型をインラインとして定義する方法は下記となります。

const MyMessage = ({ message }: { message: string }) => {
  return <div>

<h2> Welcome to the {message} of React and TypeScript.</h2>

</div>;
}

See the Pen React with Typescript interface by dev.K | Webアプリ開発者 (@enjinia_f) on CodePen.


propsオブジェクトで定義

const MyMessage = (props: { message: string }) => {
  return <div>

<h2>Welcome to the {props.message} of React and TypeScript.</h2>

</div>;
}

See the Pen React with Typescript inlineで定義 by dev.K | Webアプリ開発者 (@enjinia_f) on CodePen.


interfaceで定義

ReactとTypeScriptでコンポーネントにPropsとしてObjectを渡していく方法です。

TypeScriptを使用すると、interfaceの形式で複雑な型の定義をできます。

これは、他のプロパティを含むオブジェクトなど、アプリケーションで使用する複合型がある場合に役立ちます。

これによって、厳密なチェックが行われ、それなしで生成された可能性のあるバグの数が減少します。

interfaceを使用して、関数コンポーネントの関数内のprops引数に型注釈を付けます。

interface MessageProps {
  message: string;
};

const MyMessage = (props: MessageProps) => {
  return<div>

<h2>Welcome to the {props.message} of React and TypeScript. </h2>

</div>;
}

子のコンポーネントには、メッセージの引数として文字列しか受け付けないことになっています。

では、これをAppコンポーネントの中で使ってみましょう。

このMyMessageコンポーネントレンダリングロジックに追加します。

function App() {
  return (
    <div className="App">
      <header className="App-header">

<MyMessage message="world" />

      </header>
    </div>
  );
}

interface MessageProps {
  message: string;
};

const MyMessage = (props: MessageProps) => {
  return <div>Welcome to the {props.message} of React and TypeScript. </div>;
};

export default App;

propsのmessageとして値の文字列である『world』を子に渡してあげます。

See the Pen React with Typescript interface by dev.K | Webアプリ開発者 (@enjinia_f) on CodePen.


複数の場合で、見てみましょう。

たとえば、文字列とブール値で3つのpropsを受け入れるコンポーネント型注釈を付けてみましょう。

interface UserProps {
  name: string;
  age: number;
  country: string;
};

function UserData({name, age, country}: UserProps) {
  return (
    <div>
      <h2>{name}</h2>
      <h2>{age}</h2>
      <h2>{country}</h2>
    </div>
  );
}

export default function App() {
const obj = {...{name: 'Taro', age: 30, country: 'Japan'}};

  return (
    <div>
      <UserData {...obj} />
    </div>
  );
}

スプレッド構文(...)を使用して、オブジェクトのプロパティをpropsとしてコンポーネントに渡しています。

UserPropsinterfaceは、3つのプロパティを持つオブジェクトを表します。

See the Pen React with Typescript interface 複数 by dev.K | Webアプリ開発者 (@enjinia_f) on CodePen.


コンポーネントレンダリングするときは、propsの種類に応じてpropsの値を設定する必要があります。

基本的なpropsの型の種類は、様々な種類の型を提案します。

エイリアス(type alias)

Reactアプリケーションでは、あまりinterfaceは役に立つ事がありません。

interfaceを使うこともできますが、interfaceが機能しない場合もあるので、一貫性と明確性のためにエイリアス(type alias)を使うのがベストとなります。

ですが、新しいオブジェクトまたはオブジェクトのメソッドを定義する必要がある場合は、interfaceの方が適しています。

たとえば、Reactアプリケーションでは、特定のコンポーネントが受け取るpropsを定義する必要がある場合、エイリアスではなくinterfaceを使用するのが理想的です。

TypeScriptの型システムが、実装から状態の型を定義することにより、読み取り専用の型を正しく推測できるようにしました。

エイリアスは、同じ型を再利用したいときに使うと便利です。

型の定義が一箇所になるため、保守性が向上します。

基本的には、オブジェクトタイプだけでなく、任意のタイプに名前を付けることができます。

// primitive
type SampleString = string

// function
type SetNum = (x: number, y: number) => void

// union
type ID = number | string

// tuple
type Data = [number, string]

// index signature
type NumbersName = {
  [key: string]: string
}

// object
type Obj = {
  x: number
  y?: boolean
  handler: () => void
}

エイリアスは、プリミティブだけでなく、オブジェクト型、ユニオン型、タプル型、および交差型を表すために使用できます。

エイリアスが必要な状況は、通常より複雑なpropsの関係の場合がほとんどです。

エイリアスは、typeキーワードを付けて宣言します。

type Props = {
  title: string,
  score: number
}

const App = ({ title, score }: Props) => (
  <h1>{title} = {score}</h1>
)

typeオブジェクトを使えば、propsの型をインラインで記述する手間が省けます。

変数名を使用した場合、その変数が表す値として評価され、エイリアスも同じように機能します。

type userName = string;
type userId = string | number; 
type arr = number[];

特定の値を表すために使用される通常のJavaScript変数のようなものだと考えてください。

型のエイリアスを使用すると、そのエイリアスが表す型が評価されます。

変数と同様に、同じ型のエイリアスを複数回宣言することはできません。

また、TypeScriptがエイリアスを推論することはなく、明示的にアノテーションしなければなりません。

型に名前を与えることで可読性が上がる場合があります。

型に名前があると、その型が何を意味しているのかがコードの読み手に伝わりやすくなります。

type PersonAge = number;
type PersonName = string;
type PersonMail = string;
type Person = {
  age: PersonAge,
  name: PersonName,
  mail: PersonMail
};

const personAge: PersonAge = 30
const personName: PersonName = "Taro"
const personMail: PersonMail = "xxx.xxx@gmail.com"
const person: Person = {
  age: personAge,
  name: personName,
  mail: personMail
};

console.log(person);

コンソールの出力は下記で確認可能です。

https://codepen.io/enjinia_f/pen/YzawvzP/?editors=1011

上記のように、エイリアスを使用すると、カスタム名のエイリアスで型を定義できます。

エイリアスは、object,、array、stringなどのより複雑な型のようなプリミティブに使用できます。

宣言のマージと拡張

interfaceでは可能ですが、エイリアスでは不可能なことのひとつに、宣言のマージがあります。

宣言のマージは、TypeScriptコンパイラが、同じ名前を持つ2つ以上のinterfaceを1つの宣言にマージするときに行われます。

例えば、Userという2つのinterfaceがあり、それぞれ異なるプロパティを持つとします。

interface User {
  userName: string;
};

interface User {
  personName: string;
};

const person: Person = {
  userName: "Taro",
  personName: "Hanako"
};

上記の場合、TypeScriptは自動的に両方のinterfaceの宣言を一つにまとめてしまうので、このUser interfaceを使うと、両方のプロパティを持つことになります。

宣言のマージはエイリアスに対しては機能しません。

もし同じ名前で、異なるプロパティを持つ二つの型を作ろうとすると、TypeScriptはエラーをスローするはずです。

そして、どちらも拡張がサポートされています。

TypeScriptで型を拡張したい場合があります。

interfaceは別のinterfaceを拡張できます。

これにより、あるinterfaceを別のinterfaceにコピーして、再利用できるようになります。

これにより、はるかに柔軟性が高まります。

TypeScriptで型を拡張するには、extendsキーワードを使用できます。

単一、複数のinterface、またはクラスを拡張できます。

複数のinterfaceをカンマで区切って拡張することができます。

interface PersonInterface {
  name: string;  
};
interface DataInterface extends PersonInterface {
 city: string;
};
interface UserInterface extends PersonInterface {
  city: string;
};

class User implements UserInterface {
  name: string = 'Taro';
  city: string = 'Tokyo';
};
class Data implements DataInterface {
  name: string = 'Hanako';
  city: string = 'Osaka';
};

下記では別の例として、Dataタイプを拡張した、UserDataのinterfaceを作成しています。

type Data = {
  name: string;
  dateCreated: string;
  type: string;
};

interface UserData extends Data {
  UserId: string;
};

UserDataに文字列である、UserIdフィールドを追加し、残りをDataから継承することで拡張しています。

interfaceを拡張すると、元のinterfaceと同じプロパティに加えて、新しいinterfaceを作成することになります。

interfaceエイリアスの唯一の違い、それはエイリアスは常に閉じられていますが、interfaceでは複数回宣言することで拡張ができ、単一のinterfaceとして扱われる事です。

interface Point {
  x: number
};
interface Point {
  y: number
};
const point: Point = {x: 1, y: 2}

エイリアスは、その宣言の外で変更することはできません。

type Name = {
  name: string
};

type Name = {
  age: number
};


// Error: duplicate identifier Name

Intersection(交差型)

交差型は、複数の型を1つの型にまとめることができます。

交差型を作成するには、&キーワードを使用する必要があります。

type Name = {
  name: string
};

type Age = {
  age: number
};

type Person = Name & Age;

2つのinterfaceを組み合わせた新しい交差型を作ることができることです。

Union type(ユニオン型)

ユニオン型または共用型は、1つまたはいくつかの型の値を持つことができる新しい型を作成することができます。

ユニオン型を作成するには、( | )キーワードを使用する必要があります。

type Man = {
  name: string
};

type Woman = {
  name: string
};

type Person = Man | Woman;

2つのinterface組み合わせた新しいユニオン型を作ることはできますが、その逆はできません。

逆とは下記になります。

interface Man {
  name: string
};

interface Woman {
  name: string
};

type Person = Man | Woman;

Tuples type(タプル型)

タプル型はTypeScriptで非常に有用な概念であり、異なるデータ型の2つの値のセットを含む、新しいデータ型をもたらしました。

type Sample = [string, number];

しかし、TypeScriptでは、タプルを宣言できるのはエイリアスだけで、interfaceは使用できません。

TypeScriptではタプル型interfaceで宣言することはできませんが、interfaceの中でタプル型を使うことは可能です。

interface Sample {
  value: [string, number]
};

interfaceでタイプを使うのと同じ結果を得られることがわかります。

children props

コンポーネントがpropsを受け取ってレンダリングするChildren機能は、Reactの最も価値のある機能の1つでもあります。

再利用可能なコンポーネントの作成が簡単になります。

マークアップまたはアクションでカプセル化するだけです。

children propsの型を明示的に定義すると、その型にいくつかの異なるオプションがあります。

一部のプロパティをオプションにしたい場合は、それぞれのpropsタイプでそれを行います。

ReactでChildrenを渡すとどうなるのか?

Childrenは特別なpropsで、どんな型の要素でも渡すことが可能です。

数値、文字列、boolean、要素の配列、あるいは他のコンポーネントも可能です。

それでは、どのように型を確認すればよいのでしょう。

もちろん、任意の型として定義することもできますが、それは基本的に型チェックをしないことと同じであり、TypeScriptを使う目的そのものが失われてしまうのでお勧めしません。

いくつかの型から選択することができます。

JSX.Element

props.childrenの内容のほとんどはJSX要素で、特殊な型のJSX.Elementを使用して型付けすることができます。

その特殊な型はReact 環境でグローバルに利用できる型です。

コンポーネントレンダリングされるときに、開始タグと終了タグの間にコンテンツを保持します。

type ButtonProps = {
  children: JSX.Element
};

const Component = ({ children }: ButtonProps) => <button>{children}</button>

export function Child() {
  return (

<Component>
<span>children</span>
</Component>

  )
}

子は単一のJSX要素である必要があります。複数の子、または文字列などを許可しません。

JSX.Element [ ]

<Component>
<span>children</span>
<i>icon</i>
</Component>

こちらは、複数のJSX要素を許可します、ですが文字列、数字などは許可しません。

JSX.Element | JSX.Element []

単一または複数のJSX要素を許可します、文字列、数値などは許可しません。

interface MessageProps {
  children: JSX.Element | JSX.Element[];
  notice: boolean;
};
 
function Message({ children, notice }: MessageProps) {
  return (
    <div>
     {notice ? 'message: ' : 'message: '}
      {children}
    </div>
  );
}

interfaceのchildren propsを確認してみると、単一の要素であるJSX.Elementまたは複数の要素の配列であるJSX.Element[ ]を受け取ります。

要素を子として使用してmessageを示すことが可能となります。

See the Pen React with Typescript props.children by dev.K | Webアプリ開発者 (@enjinia_f) on CodePen.


下記は複数のChildrenとして示しております。

function App() {
  return (
    <div className="App">
      <header className="App-header">

<Message notice={false}>
  <span>Hello World. </span>
  <span>children</span>
</Message>
   
      </header>
    </div>
  );
}

上記以外の、選択できる型はございます。

React.ReactChild

1つのReact要素、文字列、または数値を許可します。

React.ReactChild [ ]

複数のReact要素、文字列、または数値を許可します。

type Sample = {
  name: string;
  children?:
    | React.ReactChild
    | React.ReactChild[];
};

React.ReactChild | React.ReactChild [ ]

単一または複数のReact要素、文字列、または数値を許可します。

React.ReactNode

数の子、文字列、数値、フラグメント、ポータルを許可します。

See the Pen React with Typescript Props React.ReactNode by dev.K | Webアプリ開発者 (@enjinia_f) on CodePen.


React.ReactNode | React.ReactNode[ ]

ReactNodeは単純に、値がReactのツリーの一部として属することができることを示す型であり、言い換えれば、JSXにそれを差し込むと動作します。

childrenと呼ばれるpropsとして多くのコンポーネントの1つを渡します。

See the Pen React with Typescript React.ReactNode | React.ReactNode[] by dev.K | Webアプリ開発者 (@enjinia_f) on CodePen.

<MyMessage>
   <h3>Hello World</h3>
</MyMessage>

上記で確認してみると、MyMessageは有効なReactNodeとして受け入れられる、ReactElementとして扱われたJSXのラッパーとして機能しました。

これは、HTML要素をネストしてUIを作成するのと同じように、JSX要素を使用できるため、一般的で頻繁に使用されます。

childrenのおさらいも含めて、他の例でも見ていきましょう。

type Props = {
  content: string,
  children: JSX.Element;
};

const Child = ({ content, children }: Props) => (
  <div>
    <h1>{content}</h1>
    {children}
  </div>
);

オプションにしたい場合は、タイプアノテーションの前にクエスチョンマーク( ? )を付けます。

type Props = {
content: string,
children?: JSX.Element;

};

タグなしでPropsオブジェクトを作成できることをコンパイラに通知します。

JSX.Elementは、子要素が単一のReact要素であることが要求される場合はよいでしょう。

しかし、複数の子要素は許しません。

そこで、下記のように調整します。

type Props = {
content: string,
children?: JSX.Element | JSX.Element[];
};

JSX.Elementの欠点は、文字列を許さないことです。

そこで、ユニオン型に文字列を追加することができます。

type Props = {
  content: string;
  children:
    | JSX.Element
    | JSX.Element[]
    | string
    | string[];
};

ですが、数字についてはどうでしょうか?

幸いなことに、React.ChildというReact要素は、文字列、数字を含む標準の型があります。

そこで、下記のように子要素の型を広げることができます。

type Props = {
  content: string;
  children?:
    | React.ReactChild
    | React.ReactChild[];
};

React.ReactChild|React.ReactChild[]は、必要な値の幅を与えてくれますが、少し冗長となってます。

ReactNodeは、より簡潔なオプションです。

type Props = {
  content: string;
  children?: React.ReactNode;
};

ReactNodeでは、複数の要素、文字列、数値、フラグメント、ポータルを使用できます。

型エラーの検証

コンポーネントに間違ったpropsのセットまたは間違った値の型を提供した場合、TypeScriptはコンパイル時に間違ったpropsの値について警告します。

先述の文字列を、数値として渡してみます。

function App() {
  return (
    <div className="App">
      <header className="App-header">

<MyMessage message={100} />

      </header>
    </div>
  );
}

interface MessageProps {
  message: string;
};

const MyMessage = (props: MessageProps) => {
  return <div>Welcome to the {props.message} of React and TypeScript. </div>;
}

messageのpropsを数値として追加した場合、TypeScriptはエラーをスローし、入力のバグを見つけるのに役立ちます。

これはコードベースに隠れることなく、開発中にエラーがキャッチされます。

Type 'number' is not assignable to type 'string'

上記のように表示され、型エラーがある場合、Reactはコンパイルすらしません。

必要なすべてのプロパティを渡さずにコンパイルするとエラーが発生します。

読み取り専用プロパティの指定

interfaceのプロパティを読み取り専用としてマークすることもできます。

これを行うには、プロパティのキーの前にreadonlyキーワードを追加します。

interface Props {
  content: string;
  totalCost: number;
  readonly dateCreated: Date;
};

読み取り専用プロパティは、オブジェクトが最初に作成されたときにのみ変更可能です。

つまり、その値を再割り当てしようとすると、コンパイラはエラーをスローします。

React.FCとReact.VFCについて

React.FCは、Typescript + Reactプログラマーの間で一般的に使用される型です。

React.FCはアロー関数を使って書かれたコンポーネントの標準的な型です。

FCは『Functional Component』の略となります。

children小道具をReactNodeとして宣言するのは完全に有効な選択肢ですが、さらにコードを削りたい場合は、React.FCを使用することでした。

React 18のリリース以降、React.FCには暗黙の子が含まれなくなり、React.VFCは非推奨になりました。

VFCまたはVoid FunctionComponentインターフェースは不要になり、FCまたはFunctionComponentのインターフェイスからchildrenプロパティが削除されました。

Reactが日々進化するにつれて、FCの代わりにVFCを使用することはもはや適切ではありません。

TypeScriptでのReact経験者は、それらから離れる必要があります。

本日から学び始めた初学者様は、これらFCまたはVFCを使用してもメリットはございません、無理に学習する必要はありません。

ですので当記事では、childrenの解説の際にこの、React.FCは含めませんでした。

最後に

TypeScriptの優れたツール機能と型の安全機能を利用するために、Reactでそれほど多くの型付けや定型コードを記述する必要がないことはすでにおわかりかと思います。

Reactではコンポーネントは非常に重要であり、数回のキーストロークで必要なものがすべて揃っています。

Reactコンポーネントは、TypeScriptから大きな恩恵を受けることができます。

コンポーネントの入力は、コンポーネントのpropsを検証するのに特に役立ちます。

本日は以上となります。

最後までこの記事を読んで頂きありがとうございます。

プライバシーポリシー