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

React NativeでTypeScriptを使用する

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

JavaScript!私たちは皆、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が同梱されているため、TypeScriptでReact Nativeアプリをテストするには、devDependenciests-jestを追加します。

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を理解している必要があります。一部のライブラリは、基になるJavaScriptの形状を記述できる.d.tsファイル(型宣言/型定義ファイル)を含むパッケージを公開します。他のライブラリの場合、@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 アプリであるため、開発依存関係として保存しました。ライブラリを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開発環境で楽しんでください!