LoginSignup
1
0

TypeScript × React-Tutorial: Tic-Tac-Toe / 三目並べ

Last updated at Posted at 2023-08-13

この記事では,以下のサイトを解説をします.

自分が自習時に作成したプログラムとサイトは,以下になります.

「React-Tutorial: Tic-Tac-Toe / 三目並べ」にTypeScriptで取り組みました.
その時に自分が分からなかった箇所,詰まった箇所を中心に解説をします.

はじめに

「React-Tutorial: Tic-Tac-Toe / 三目並べ」は,ゲームを作りながら学べるReact初心者向けサイトです.
サイトで記述されている言語は,JavaScriptです.
サイトの言語がJavaScriptなのにTypeScriptで挑んだため,色々な警告やエラーに直面しました.

React,TypeScript未経験の自分がいきなりチュートリアルに挑んだ時,欲しかった解説を残しておきます.

ローカルでTypeScriptプロジェクトを起動

チュートリアルに入る前に,ローカルでTypeScriptプロジェクトを起動します.
まず,以下からNode.jsをダウンロードします.

そして,以下のコマンドを実行します.

npm install -g npx
npx create-react-app react-tutorial --template typescript
cd react-tutorial
npm start

以下の画面が出てきたらOKです.
image.png

エラーを確認

チュートリアルで利用・編集するのは,react-tutorial/src/App.tsxです.
例として,プログラムの全文(import React ... default App;)を以下に書き換えます.

App.tsx
export default function App() {
  return <p> Hello world! </p>
}

画面が以下のように変化します.
image.png
次に,同じくApp.tsxの全文をチュートリアルの最初に出てくるApp.js(116行)に書き換えます.
画面が以下のように変化します.
image.png
「完成したときにどのような見た目になるか、以下で確認できます。」というプログラムを利用したのに9件のエラーが出てきます.
JavaScriptでは許容されるがTypeScriptでは許容されない記述がエラーとして出ています.
完成したときの見た目はチュートリアルのサイトで確認することにして,先に進みましょう.

チュートリアルに挑戦

チュートリアルを読み進め,途中に出てくるプログラムでApp.tsxを書き換えます.
例えば,以下のプログラムで以下の画面が出てきます.

App.tsx
export default function Square() {
  return (
    <>
      <button className="square">X</button>
      <button className="square">X</button>
    </>
  );
}

image.png
react-tutorial/src/index.cssを編集し,margin: 0;の記述を削除,styles.cssの内容を追記すると,画面表示がチュートリアルのサイトと同じになります.
image.png

引数の型に関するエラーを修正1(05.tsx

チュートリアルを進めていくと,以下のエラーが出ます.
Binding element 'value' implicitly has an 'any' type.
image.png
これは,関数Squareの引数valueの型が指定されていないために起きたエラーです.
1行目を以下のように書き換えて,型情報を追加するとエラーが解消されます.

App.tsx
- function Square({ value }) {
+ function Square({ value }: { value?: string }) {

ここで選択候補となるvalueの型は,4種類あります.
VSCode上でvalueにカーソルを合わせた時に表示される情報は,以下になります.

  • { value }: { value: any }(parameter) value: any
  • { value }: { value?: any }(parameter) value: any
  • { value }: { value: string }(parameter) value: string
  • { value }: { value?: string }(parameter) value: string | undefined

1, 3番目の型は,プログラムの9行目以降でエラーが出ます.
Property 'value' is missing in type '{}' but required in type '{ value: any; }'.
image.png
関数Squareの引数valueが必須にも関わらず,その値が無いためにエラーが発生しています.
<Square value="1" />のように書き換えていくとエラーが解消されます.

2, 4番目の型はundefinedを許容しており,関数Squareの引数valueが無くても問題ないため,エラーが出ません.
JavaScriptやTypeScriptにおいて,valueの後の?(クエスチョンマーク,疑問符)はオプションパラメータと呼び,重要な意味があります.
関数の引数やインターフェースのプロパティを省略可能であることを意味します.

JavaScriptではなくTypeScriptを利用しているので,その作法に則り,なるべく厳密に型を指定します.
{ value }: { value?: any }は,なるべく使わないようにします.
初めは{ value }: { value?: string }と記述し,後ほど{ value }: { value: string }にリファクタリングするのがお勧めです.

useStateの型に関するエラーを修正(08.tsx

チュートリアルを進めていくと,以下のエラーが出ます.
Argument of type '"X"' is not assignable to parameter of type 'SetStateAction<null>'.
これは,関数Squareの引数valueの型が指定されていないために起きたエラーです.
1行目を以下のように書き換えて,型情報を追加するとエラーが解消されます.

image.png
これは,useStateで利用するvalueの型が指定されていないために起きたエラーです.
useStateに関する行を以下のように書き換えて,型情報を追加するとエラーが解消されます.

App.tsx
- const [value, setValue] = useState(null);
+ const [value, setValue] = useState<string | null>(null);

VSCode上でvalueにカーソルを合わせた時に表示される情報は,const value: string | nullに変化します.
JavaScriptとTypeScriptでは,undefinednullは異なる型です.
null型をundefined型で代用できる場合は,const [value, setValue] = useState<string>();に書き換えても問題ありません.

引数の型に関するエラーを修正2(10.tsx

チュートリアルを進めていくと,以下のエラーが出ます.
Binding element 'value' implicitly has an 'any' type.
Binding element 'onSquareClick' implicitly has an 'any' type.
これは,関数Squareの引数valueonSquareClickの型が指定されていないというエラーです.
引数が2つ以上ある場合,以下のように型エイリアス(Type Alias)を使うことが一般的です.

App.tsx
+ type Props = {
+   value: string,
+   onSquareClick?: React.MouseEventHandler<HTMLButtonElement>,
+ }

- function Square({ value, onSquareClick }) {
+ function Square({ value, onSquareClick }: Props) {
  return (
    <button className="square" onClick={onSquareClick}>
      {value}
    </button>
  );
}

type Props = {...}が型エイリアスです.
型エイリアスを使わずにSquare()の括弧内に型を書いてもエラーが消えますが,可読性や変数の再利用を考慮すると非推奨です.

引数の型に関するエラーを修正3(12.tsx, 14.tsx, 16.tsx

チュートリアルを進めていくと,以下のエラーが出ます.
Parameter 'i' implicitly has an 'any' type.
Parameter 'squares' implicitly has an 'any' type.
Parameter 'nextSquares' implicitly has an 'any' type.
これらの修正には,型エイリアスを使わなくても良いと思います.
以下のように変更します.

App.tsx
- function handleClick(i) {
+ function handleClick(i: number) {
App.tsx
- function calculateWinner(squares) {
+ function calculateWinner(squares: string[]) {
App.tsx
- function handlePlay(nextSquares) {
+ function handlePlay(nextSquares: string[]) {

引数の型に関するエラーを修正4(17.tsx, 19.tsx

チュートリアルを進めていくと,再び引数の型に関するエラーが出てきます.
新しくBoardPropsを作成して,エラーを修正します.

App.tsx
+ type BoardProps = {
+   xIsNext: boolean,
+   squares: string[],
+   onPlay: (nextSquares: string[]) => void,
+ }

- function Board({ xIsNext, squares, onPlay }) {
+ function Board({ xIsNext, squares, onPlay }: BoardProps) {

関数jumpToを以下のように修正します.

App.tsx
- function jumpTo(nextMove) {
+ function jumpTo(nextMove: number) {

以上の情報があれば,TypeScriptで「React-Tutorial: Tic-Tac-Toe / 三目並べ」が完了できます.

終わりに

この記事で紹介したチュートリアルは,Reactを実践しながら学ぶことができ,実際にweb画面で動くものが作れるお勧めの教材です.
JavaScriptを利用するのであれば,この記事に記載したエラーに直面することなく,チュートリアルのwebサイトだけでスムーズに学習できると思います.

開発環境がTypeScript × Reactの場合,この記事を参考にしながらチュートリアルに取り組んでみてはいかがでしょうか.
JavaScriptとTypeScriptの違いも勉強できて,一石二鳥です.

関連記事:

1
0
1

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
1
0