xref: /expo/docs/pages/guides/typescript.mdx (revision ae642c8a)
1---
2title: Using TypeScript
3description: An in-depth guide on configuring an Expo project with TypeScript.
4---
5
6import { Terminal } from '~/ui/components/Snippet';
7
8> Example project: [with-typescript](https://github.com/expo/examples/tree/master/with-typescript)
9
10Expo has first-class support for [TypeScript](https://www.typescriptlang.org/). The JavaScript interface of the Expo SDK is completely written in TypeScript.
11
12To get started, create a **tsconfig.json** in your project root:
13
14<Terminal cmd={['$ touch tsconfig.json']} />
15
16For SDK 48 and above, running `npx expo start` will prompt you to install the required dependencies, such as `typescript` and `@types/react`, and automatically configure your **tsconfig.json**. For SDK 47 and below, the command will also prompt to install `@types/react-native` as an additional dependency.
17
18Rename files to convert them to TypeScript. For example, you would rename **App.js** to **App.tsx**. Use the **.tsx** extension if the file includes React components (JSX). If the file did not include any JSX, you can use the **.ts** file extension.
19
20<Terminal cmd={['$ mv App.js App.tsx']} />
21
22You can now run `yarn tsc` or `npx tsc` to typecheck the project.
23
24## Base configuration
25
26> You can disable the TypeScript setup in Expo CLI with the environment variable `EXPO_NO_TYPESCRIPT_SETUP=1`
27
28A project's **tsconfig.json** should extend the `expo/tsconfig.base` by default. This sets the following default [compiler options][tsc-compileroptions] (which can be overwritten in your project's **tsconfig.json**):
29
30- `"allowJs"`: `true`
31  - Allow JavaScript files to be compiled. If you project requires more strictness, you can disable this.
32- `"esModuleInterop"`: `true`
33  - Improve Babel ecosystem compatibility. This also sets `allowSyntheticDefaultImports` to `true`, allowing default imports from modules with no default export.
34- [`"jsx"`][tsc-jsx]: `"react-native"`
35  - Preserve JSX, and converts the `jsx` extension to `js`. This is optimized for bundlers that transform the JSX internally (like Metro).
36- `"lib"`: `["DOM", "ESNext"]`
37  - Allow using the latest [ECMAScript proposed features and libraries](https://github.com/tc39/proposals).
38- [`"moduleResolution"`][tsc-moduleresolution]: `"node"`
39  - Emulate how Metro and webpack resolve modules.
40- `"noEmit"`: `true`
41  - Only use the TypeScript compiler (TSC) to check the code. The Metro bundler is responsible for compiling TypeScript to JavaScript.
42- `"resolveJsonModule"`: `true`
43  - Enables importing **.json** files. Metro's default behavior is to allow importing json files as JS objects.
44- `"skipLibCheck"`: `true`
45  - Skip type checking of all declaration files (`*.d.ts`).
46- `"target"`: `"ESNext"`
47  - Compile to the latest version of ECMAScript.
48
49[tsc-jsx]: https://www.typescriptlang.org/docs/handbook/jsx.html
50[tsc-compileroptions]: https://www.typescriptlang.org/docs/handbook/compiler-options.html
51[tsc-moduleresolution]: https://www.typescriptlang.org/docs/handbook/module-resolution.html
52
53## Project configuration
54
55Expo CLI will automatically modify your **tsconfig.json** to the preferred default which is optimized for universal React development:
56
57```json tsconfig.json
58{
59  "extends": "expo/tsconfig.base",
60  "compilerOptions": {}
61}
62```
63
64The default configuration is forgiving and makes it easier to adopt TypeScript. If you'd like to opt-in to more strict type checking, you can add `"strict": true` to the `compilerOptions`. We recommend enabling this to minimize the chance of introducing runtime errors.
65
66Certain language features may require additional configuration, for example if you'd like to use decorators you will need to add the `experimentalDecorators` option. For more information on the available properties see the [TypeScript compiler options documentation](https://www.typescriptlang.org/docs/handbook/compiler-options.html) documentation.
67
68## Starting from scratch: using a TypeScript template
69
70<Terminal
71  cmd={['$ npx create-expo-app -t expo-template-blank-typescript']}
72  cmdCopy="npx create-expo-app -t expo-template-blank-typescript"
73/>
74
75The easiest way to get started is to initialize your new project using a TypeScript template, then run `yarn tsc` or `npx tsc` to "typecheck" the project.
76
77When you create new source files in your project you should use the **.ts** extension or the **.tsx** if the file includes React components.
78
79{/*
80
81## Path Aliases
82
83> Available since SDK 49.
84
85SDK 49 projects will need to enable this feature in the project's **app.json**:
86
87```json app.json
88{
89  "expo": {
90    "experiments": {
91      "tsconfigPaths": true
92    }
93  }
94}
95```
96
97Expo CLI supports [path aliases](https://www.typescriptlang.org/docs/handbook/module-resolution.html#path-mapping) in your project's **tsconfig.json** automatically. This enables you to import modules using a custom alias instead of a relative path.
98
99For example, if you have a file at `src/components/Button.tsx` and wish to import it using the alias `@/components/Button` as follows:
100
101```tsx
102import Button from '@/components/Button';
103```
104
105Then simply add the alias `@/` in the project's **tsconfig.json** and set it to the `src` directory:
106
107```json tsconfig.json
108{
109  "compilerOptions": {
110    "baseUrl": ".",
111    "paths": {
112      "@/*": ["src/*"]
113    }
114  }
115}
116```
117
118- Expo CLI must be restarted to update path aliases when you change the **tsconfig.json**. You don't need to clear the Metro cache when the aliases change.
119- `jsconfig.json` can be used instead of `tsconfig.json` if you are not using TypeScript.
120- Path aliases add additional resolution time when defined.
121- Path aliases are Metro-only (including Metro web) and not supported by `@expo/webpack-config`.
122- This feature requires additional setup in bare projects. See the [versioned Metro setup guide](/versions/latest/config/metro#bare-workflow-setup) for more information.
123
124## Absolute Imports
125
126> Available since SDK 49.
127
128SDK 49 projects will need to enable this feature in the project's **app.json**:
129
130```json app.json
131{
132  "expo": {
133    "experiments": {
134      "tsconfigPaths": true
135    }
136  }
137}
138```
139
140Absolute imports from the project root directory are enabled automatically when the project contains a **tsconfig.json** or **jsconfig.json** file.
141
142This enables imports like:
143
144```tsx
145import Button from 'src/components/Button';
146// Imports `<project root>/src/components/Button`
147```
148
149The base directory can be modified in the **tsconfig.json** (or **jsconfig.json**) using the [`baseUrl`][baseurl] option:
150
151```json tsconfig.json
152{
153  "compilerOptions": {
154    "baseUrl": "src"
155  }
156}
157```
158
159- [`compilerOptions.baseUrl`][baseurl] is automatically set to `.` when the `tsconfig.json` or `jsconfig.json` files exist.
160- Node modules take precedence over absolute imports, so you cannot overwrite a node module import with an absolute import.
161- Expo CLI must be restarted to update [`compilerOptions.baseUrl`][baseurl] when you change the **tsconfig.json**.
162- `jsconfig.json` can be used instead of `tsconfig.json` if you are not using TypeScript.
163- Absolute imports are Metro-only (including Metro web) and not supported by `@expo/webpack-config`.
164- This feature requires additional setup in bare projects. See the [versioned Metro setup guide](/versions/latest/config/metro#bare-workflow-setup) for more information.
165
166[baseurl]: https://www.typescriptlang.org/docs/handbook/module-resolution.html#base-url
167
168*/}
169
170## TypeScript for config files
171
172You may find that you want to use TypeScript for the config files in your project, like the **webpack.config.js**, **metro.config.js**, or **app.config.js**. These will require a little extra setup. You can utilize the [`ts-node` require hook](https://github.com/TypeStrong/ts-node#programmatic) to _import_ TypeScript files into your JS config file, meaning any import can be TypeScript, but the root file will still need to be JavaScript.
173
174<Terminal cmd={['$ yarn add -D ts-node typescript']} />
175
176### webpack.config.js
177
178> You may need to install the `@expo/webpack-config` package.
179
180```js webpack.config.js
181require('ts-node/register');
182module.exports = require('./webpack.config.ts');
183```
184
185```ts webpack.config.ts
186import createExpoWebpackConfigAsync from '@expo/webpack-config/webpack';
187import { Arguments, Environment } from '@expo/webpack-config/webpack/types';
188
189module.exports = async function (env: Environment, argv: Arguments) {
190  const config = await createExpoWebpackConfigAsync(env, argv);
191  // Customize the config before returning it.
192  return config;
193};
194```
195
196### metro.config.js
197
198```js metro.config.js
199require('ts-node/register');
200module.exports = require('./metro.config.ts');
201```
202
203```ts metro.config.ts
204import { getDefaultConfig } from 'expo/metro-config';
205
206const config = getDefaultConfig(__dirname);
207
208module.exports = config;
209```
210
211### app.config.js
212
213Technically **app.config.ts** is supported by default, but it doesn't support external TypeScript modules, or **tsconfig.json** customization. You can use the following approach to get a more comprehensive TypeScript setup.
214
215```js app.config.js
216require('ts-node/register');
217module.exports = require('./app.config.ts');
218```
219
220```ts app.config.ts
221import { ExpoConfig } from 'expo/config';
222
223// In SDK 46 and lower, use the following import instead:
224// import { ExpoConfig } from '@expo/config-types';
225
226const config: ExpoConfig = {
227  name: 'my-app',
228  slug: 'my-app',
229};
230
231export default config;
232```
233
234## Learning how to use TypeScript
235
236A good place to start learning TypeScript is the official [TypeScript Handbook](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html).
237
238### TypeScript and React components
239
240We recommend reading over and referring to the [React TypeScript CheatSheet](https://github.com/typescript-cheatsheets/react) to learn how to type your React components in a variety of common situations.
241
242### Advanced types
243
244If you would like to go deeper and learn how to create more expressive and powerful types, we recommend the [Advanced Static Types in TypeScript course](https://egghead.io/courses/advanced-static-types-in-typescript) (this requires an egghead.io subscription).
245