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

TypeScript の利用

TypeScript は、型定義を追加することで JavaScript を拡張する言語です。新しい React Native プロジェクトはデフォルトで TypeScript をターゲットにしていますが、JavaScript と Flow もサポートしています。

TypeScript の始め方

React Native CLI または Ignite のような一般的なテンプレートによって作成された新しいプロジェクトは、デフォルトで TypeScript を使用します。

TypeScript は Expo でも使用でき、Expo は TypeScript テンプレートを維持するか、プロジェクトに .ts または .tsx ファイルが追加されると、TypeScript を自動的にインストールして設定するよう求めます。

npx create-expo-app --template

既存のプロジェクトに TypeScript を追加する

  1. TypeScript、型定義、および ESLint プラグインをプロジェクトに追加します。
npm install -D @tsconfig/react-native @types/jest @types/react @types/react-test-renderer typescript

このコマンドは、すべての依存関係の最新バージョンを追加します。プロジェクトで使用されている既存のパッケージに合わせてバージョンを変更する必要がある場合があります。React Native Upgrade Helper のようなツールを使用すると、React Native に同梱されているバージョンを確認できます。

  1. TypeScript 設定ファイルを追加します。プロジェクトのルートに tsconfig.json を作成します。
{
"extends": "@tsconfig/react-native/tsconfig.json"
}
  1. JavaScript ファイルの名前を *.tsx に変更します。

./index.js エントリーポイントファイルはそのままにしておく必要があります。そうしないと、本番ビルドをバンドルするときに問題が発生する可能性があります。

  1. tsc を実行して、新しい TypeScript ファイルを型チェックします。
npx tsc

TypeScript の代わりに JavaScript を使用する

React Native は新しいアプリケーションのデフォルトを TypeScript にしていますが、JavaScript も引き続き使用できます。.jsx 拡張子を持つファイルは、TypeScript ではなく JavaScript として扱われ、型チェックされません。JavaScript モジュールは、TypeScript モジュールから、またその逆も同様にインポートできます。

TypeScript と React Native の仕組み

既定では、TypeScript ソースはバンドル中に Babel によって変換されます。型チェックには TypeScript コンパイラのみを使用することをお勧めします。これは、新規作成されたアプリケーションに対する tsc のデフォルトの動作です。既存の TypeScript コードを React Native に移植する場合、TypeScript の代わりに Babel を使用するには、1 つまたは 2 つの注意点があります。

React Native + TypeScript はどのように見えるか

React.Component<Props, State> を介して React コンポーネントの Props および State のインターフェースを提供できます。これにより、JSX でそのコンポーネントを操作するときに型チェックとエディターの自動補完が提供されます。

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

export type Props = {
name: string;
baseEnthusiasmLevel?: number;
};

const Hello: React.FC<Props> = ({
name,
baseEnthusiasmLevel = 0,
}) => {
const [enthusiasmLevel, setEnthusiasmLevel] = React.useState(
baseEnthusiasmLevel,
);

const onIncrement = () =>
setEnthusiasmLevel(enthusiasmLevel + 1);
const onDecrement = () =>
setEnthusiasmLevel(
enthusiasmLevel > 0 ? enthusiasmLevel - 1 : 0,
);

const getExclamationMarks = (numChars: number) =>
numChars > 0 ? Array(numChars + 1).join('!') : '';

return (
<View style={styles.container}>
<Text style={styles.greeting}>
Hello {name}
{getExclamationMarks(enthusiasmLevel)}
</Text>
<View>
<Button
title="Increase enthusiasm"
accessibilityLabel="increment"
onPress={onIncrement}
color="blue"
/>
<Button
title="Decrease enthusiasm"
accessibilityLabel="decrement"
onPress={onDecrement}
color="red"
/>
</View>
</View>
);
};

const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
greeting: {
fontSize: 20,
fontWeight: 'bold',
margin: 16,
},
});

export default Hello;

TypeScript playground で構文を詳しく調べることができます。

役立つアドバイスを見つける場所

TypeScript でカスタムパスエイリアスを使用する

TypeScript でカスタムパスエイリアスを使用するには、Babel と TypeScript の両方から動作するようにパスエイリアスを設定する必要があります。その方法は次のとおりです。

  1. カスタムパスマッピングを設定するように tsconfig.json を編集します。src のルートにあるものは、先行するパス参照なしで利用できるように設定し、テストファイルは tests/File.tsx を使用してアクセスできるようにします。
{
- "extends": "@tsconfig/react-native/tsconfig.json"
+ "extends": "@tsconfig/react-native/tsconfig.json",
+ "compilerOptions": {
+ "baseUrl": ".",
+ "paths": {
+ "*": ["src/*"],
+ "tests": ["tests/*"],
+ "@components/*": ["src/components/*"],
+ },
+ }
}
  1. プロジェクトに babel-plugin-module-resolver を開発パッケージとして追加します。
npm install --save-dev babel-plugin-module-resolver
  1. 最後に、babel.config.js を設定します(babel.config.js の構文は tsconfig.json と異なることに注意してください)。
{
presets: ['module:metro-react-native-babel-preset'],
+ plugins: [
+ [
+ 'module-resolver',
+ {
+ root: ['./src'],
+ extensions: ['.ios.js', '.android.js', '.js', '.ts', '.tsx', '.json'],
+ alias: {
+ tests: ['./tests/'],
+ "@components": "./src/components",
+ }
+ }
+ ]
+ ]
}