メインコンテンツへスキップ

React NativeでTypeScriptを使用する

·8分で読めます
Ash Furrow
Artsy ソフトウェアエンジニア

JavaScript!私たちは皆大好きです。しかし、中にはが好きな人もいます。幸いなことに、JavaScriptに強力な型を追加する選択肢は存在します。私のお気に入りはTypeScriptですが、React NativeはFlowを標準でサポートしています。どちらを好むかは好みの問題であり、それぞれがJavaScriptに型の魔法を追加するための独自のアプローチを持っています。今日は、React NativeアプリでTypeScriptを使用する方法について見ていきましょう。

この記事では、MicrosoftのTypeScript-React-Native-Starterリポジトリをガイドとして使用します。

更新: このブログ記事が書かれてから、さらに簡単になりました。このブログ記事で説明されているセットアップはすべて、たった1つのコマンドを実行するだけで置き換えられます。

npx react-native init MyAwesomeProject --template react-native-template-typescript

ただし、BabelのTypeScriptサポートにはいくつかの制限があり、上記のブログ記事で詳しく説明されています。この記事で概説されている手順はまだ機能し、Artsyは本番環境でまだreact-native-typescript-transformerを使用していますが、React NativeとTypeScriptを使い始める最速の方法は上記のコマンドを使用することです。必要であれば、後で切り替えることもいつでもできます。

いずれにせよ、楽しんでください!元のブログ記事は以下に続きます。

前提条件

あなたはいくつかの異なるプラットフォームで開発し、いくつかの異なるタイプのデバイスをターゲットにしている可能性があるため、基本的なセットアップは複雑になることがあります。まず、TypeScriptなしでプレーンなReact Nativeアプリを実行できることを確認する必要があります。React Nativeのウェブサイトの指示に従って始めてください。デバイスやエミュレータにデプロイできたら、TypeScript React Nativeアプリを開始する準備が整います。

また、Node.jsnpm、およびYarnも必要です。

初期化

通常のReact Nativeプロジェクトのひな形を作成してみたら、TypeScriptを追加する準備が整います。さあ、やってみましょう。

react-native init MyAwesomeProject
cd MyAwesomeProject

TypeScriptの追加

次のステップは、プロジェクトにTypeScriptを追加することです。以下のコマンドは、

  • プロジェクトにTypeScriptを追加します
  • プロジェクトにReact Native TypeScript Transformerを追加します
  • 空のTypeScript設定ファイルを初期化します。これは次に設定します
  • 空のReact Native TypeScript Transformer設定ファイルを追加します。これは次に設定します
  • ReactとReact Nativeの型定義を追加します

では、これらを実行してみましょう。

yarn add --dev typescript
yarn add --dev react-native-typescript-transformer
yarn tsc --init --pretty --jsx react
touch rn-cli.config.js
yarn add --dev @types/react @types/react-native

tsconfig.jsonファイルにはTypeScriptコンパイラのすべての設定が含まれています。上記のコマンドで作成されたデフォルトはほとんど問題ありませんが、ファイルを開いて次の行のコメントを解除してください。

{
/* Search the config file for the following line and uncomment it. */
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
}

rn-cli.config.jsにはReact Native TypeScript Transformerの設定が含まれています。それを開いて以下を追加してください。

module.exports = {
getTransformModulePath() {
return require.resolve('react-native-typescript-transformer');
},
getSourceExts() {
return ['ts', 'tsx'];
},
};

TypeScriptへの移行

生成されたApp.js__tests_/App.jsファイルをApp.tsxにリネームします。index.js.js拡張子を使用する必要があります。新しいファイルはすべて.tsx拡張子を使用する必要があります(ファイルにJSXが含まれていない場合は.ts)。

もし今アプリを実行しようとすると、object prototype may only be an object or nullのようなエラーが表示されるでしょう。これは、Reactからのデフォルトエクスポートと名前付きエクスポートを同じ行でインポートしようとしたために発生します。App.tsxを開き、ファイルの先頭にあるインポート文を修正してください。

-import React, { Component } from 'react';
+import React from 'react'
+import { Component } from 'react';

これの一部は、BabelとTypeScriptがCommonJSモジュールと相互運用する方法の違いに関係しています。将来的には、両者は同じ挙動に安定するでしょう。

この時点で、React Nativeアプリを実行できるはずです。

TypeScriptテストインフラの追加

React NativeにはJestが同梱されているので、React NativeアプリをTypeScriptでテストするには、ts-jestdevDependenciesに追加する必要があります。

yarn add --dev ts-jest

次に、package.jsonを開き、jestフィールドを以下に置き換えます。

{
"jest": {
"preset": "react-native",
"moduleFileExtensions": [
"ts",
"tsx",
"js"
],
"transform": {
"^.+\\.(js)$": "<rootDir>/node_modules/babel-jest",
"\\.(ts|tsx)$": "<rootDir>/node_modules/ts-jest/preprocessor.js"
},
"testRegex": "(/__tests__/.*|\\.(test|spec))\\.(ts|tsx|js)$",
"testPathIgnorePatterns": [
"\\.snap$",
"<rootDir>/node_modules/"
],
"cacheDirectory": ".jest/cache"
}
}

これにより、Jestは.tsおよび.tsxファイルをts-jestで実行するように設定されます。

依存関係の型定義ファイルのインストール

TypeScriptで最高のエクスペリエンスを得るためには、型チェッカーが依存関係の構造とAPIを理解する必要があります。一部のライブラリは、パッケージを.d.tsファイル(型宣言/型定義ファイル)と共に公開しており、これらは基礎となるJavaScriptの構造を記述できます。他のライブラリについては、@types/ npmスコープで適切なパッケージを明示的にインストールする必要があります。

たとえば、ここではJest、React、React Native、およびReact Test Rendererの型が必要になります。

yarn add --dev @types/jest @types/react @types/react-native @types/react-test-renderer

これらの宣言ファイルパッケージは、開発中にのみこれらの依存関係を使用し、ランタイムでは使用しないReact Native *アプリ* であるため、*dev* 依存関係として保存しました。NPMにライブラリを公開している場合は、これらの型依存関係の一部を通常の依存関係として追加する必要があるかもしれません。

.d.tsファイルの入手方法についてはこちらで詳しく読むことができます。

無視するファイルの追加

ソース管理では、.jestフォルダを無視するように設定する必要があります。gitを使用している場合は、.gitignoreファイルにエントリを追加するだけです。

# Jest
#
.jest/

チェックポイントとして、ファイルをバージョン管理にコミットすることを検討してください。

git init
git add .gitignore # import to do this first, to ignore our files
git add .
git commit -am "Initial commit."

コンポーネントの追加

アプリにコンポーネントを追加しましょう。Hello.tsxコンポーネントを作成します。これは教育的なコンポーネントであり、実際にアプリで書くようなものではありませんが、React NativeでTypeScriptを使用する方法を示すための、ある程度複雑なものです。

componentsディレクトリを作成し、以下の例を追加してください。

// components/Hello.tsx
import React from 'react';
import {Button, StyleSheet, Text, View} from 'react-native';

export interface Props {
name: string;
enthusiasmLevel?: number;
}

interface State {
enthusiasmLevel: number;
}

export class Hello extends React.Component<Props, State> {
constructor(props: Props) {
super(props);

if ((props.enthusiasmLevel || 0) <= 0) {
throw new Error(
'You could be a little more enthusiastic. :D',
);
}

this.state = {
enthusiasmLevel: props.enthusiasmLevel || 1,
};
}

onIncrement = () =>
this.setState({
enthusiasmLevel: this.state.enthusiasmLevel + 1,
});
onDecrement = () =>
this.setState({
enthusiasmLevel: this.state.enthusiasmLevel - 1,
});
getExclamationMarks = (numChars: number) =>
Array(numChars + 1).join('!');

render() {
return (
<View style={styles.root}>
<Text style={styles.greeting}>
Hello{' '}
{this.props.name +
this.getExclamationMarks(this.state.enthusiasmLevel)}
</Text>

<View style={styles.buttons}>
<View style={styles.button}>
<Button
title="-"
onPress={this.onDecrement}
accessibilityLabel="decrement"
color="red"
/>
</View>

<View style={styles.button}>
<Button
title="+"
onPress={this.onIncrement}
accessibilityLabel="increment"
color="blue"
/>
</View>
</View>
</View>
);
}
}

// styles
const styles = StyleSheet.create({
root: {
alignItems: 'center',
alignSelf: 'center',
},
buttons: {
flexDirection: 'row',
minHeight: 70,
alignItems: 'stretch',
alignSelf: 'center',
borderWidth: 5,
},
button: {
flex: 1,
paddingVertical: 0,
},
greeting: {
color: '#999',
fontWeight: 'bold',
},
});

おお!たくさんありますが、分解してみましょう。

  • divspanh1などのHTML要素をレンダリングする代わりに、ViewButtonなどのコンポーネントをレンダリングしています。これらは、異なるプラットフォームで動作するネイティブコンポーネントです。
  • スタイリングは、React Nativeが提供するStyleSheet.create関数を使用して指定されます。Reactのスタイルシートを使用すると、Flexboxを使用してレイアウトを制御したり、CSSの他の構成要素に似たものを使用してスタイルを設定したりできます。

コンポーネントテストの追加

コンポーネントができたので、テストしてみましょう。

テストランナーとしてJestはすでにインストールされています。コンポーネントのスナップショットテストを記述するので、スナップショットテストに必要なアドオンを追加しましょう。

yarn add --dev react-addons-test-utils

それでは、componentsディレクトリに__tests__フォルダを作成し、Hello.tsxのテストを追加しましょう。

// components/__tests__/Hello.tsx
import React from 'react';
import renderer from 'react-test-renderer';

import {Hello} from '../Hello';

it('renders correctly with defaults', () => {
const button = renderer
.create(<Hello name="World" enthusiasmLevel={1} />)
.toJSON();
expect(button).toMatchSnapshot();
});

テストが初めて実行されると、レンダリングされたコンポーネントのスナップショットが作成され、components/__tests__/__snapshots__/Hello.tsx.snapファイルに保存されます。コンポーネントを変更した場合は、スナップショットを更新し、意図しない変更がないかレビューする必要があります。React Nativeコンポーネントのテストについては、こちらで詳しく読むことができます。

次のステップ

公式のReactチュートリアルや状態管理ライブラリのReduxをチェックしてみてください。これらのリソースは、React Nativeアプリを作成する際に役立ちます。さらに、Web上のReactとReact Nativeの両方をサポートする、完全にTypeScriptで書かれたコンポーネントライブラリであるReactXPも見てみると良いでしょう。

より型安全なReact Native開発環境で楽しんでください!