xref: /expo/docs/pages/guides/typescript.mdx (revision da751fd5)
1---
2title: Use TypeScript
3description: An in-depth guide on configuring an Expo project with TypeScript.
4---
5
6import { Terminal } from '~/ui/components/Snippet';
7import { BoxLink } from '~/ui/components/BoxLink';
8import { GithubIcon } from '@expo/styleguide-icons';
9import { Tabs, Tab, TabsGroup } from '~/ui/components/Tabs';
10
11Expo has first-class support for [TypeScript](https://www.typescriptlang.org/). The JavaScript interface of the Expo SDK is completely written in TypeScript.
12
13<BoxLink
14  title="with-typescript"
15  description="See the example project on GitHub."
16  href="https://github.com/expo/examples/tree/master/with-typescript"
17  Icon={GithubIcon}
18/>
19
20<TabsGroup>
21
22## Get started
23
24### Quick start with a template
25
26The easiest way to get started is to initialize your new project using a TypeScript template:
27
28<Terminal cmd={['$ npx create-expo-app -t expo-template-blank-typescript']} />
29
30For npm, add the following `script` to the **package.json**:
31
32{/* prettier-ignore */}
33```json package.json
34{
35  "scripts": {
36    "tsc": "tsc"
37    /* @hide ... */ /* @end */
38  }
39}
40```
41
42Then, to type-check the project, run the following command:
43
44<Tabs>
45<Tab label="npm">
46
47<Terminal cmd={['$ npm run tsc']} />
48
49</Tab>
50
51<Tab label="yarn">
52
53<Terminal cmd={['$ yarn tsc']} />
54
55</Tab>
56</Tabs>
57
58When you create new source files in your project you should use the **.ts** extension or the **.tsx** if the file includes React components.
59
60### In an existing project
61
62Rename files to convert them to TypeScript. For example, rename **App.js** to **App.tsx**. Use the **.tsx** extension if the file includes React components (JSX). If the file does not include any JSX, you can use the **.ts** file extension.
63
64<Terminal cmd={['$ mv App.js App.tsx']} />
65
66> **For SDK 48 and higher**, running `npx expo start` prompts you to install the required dependencies, such as `typescript` and `@types/react`. **For SDK 47 and below**, the command also prompts you to install `@types/react-native` as an additional dependency.
67
68For npm, add the following `script` to the **package.json**:
69
70{/* prettier-ignore */}
71```json package.json
72{
73  "scripts": {
74    "tsc": "tsc"
75    /* @hide ... */ /* @end */
76  }
77}
78```
79
80You can now run `npm run tsc` or `yarn tsc` to type-check the project.
81
82## Base configuration
83
84> You can disable the TypeScript setup in Expo CLI with the environment variable `EXPO_NO_TYPESCRIPT_SETUP=1`
85
86A project's **tsconfig.json** should extend the `expo/tsconfig.base` by default. This sets the following default [compiler options](https://www.typescriptlang.org/docs/handbook/compiler-options.html) (which can be overwritten in your project's **tsconfig.json**):
87
88## Project configuration
89
90Expo CLI will automatically modify your **tsconfig.json** to the preferred default which is optimized for universal React development:
91
92```json tsconfig.json
93{
94  "extends": "expo/tsconfig.base",
95  "compilerOptions": {}
96}
97```
98
99The default configuration for TypeScript is user-friendly and encourages adoption. However, if you prefer strict type checking, you can enable it by adding `"strict": true` to the `compilerOptions`. We recommend enabling this to minimize the chance of introducing runtime errors.
100
101Some language features may require additional configuration. For example, if want to use decorators you'll need to add the `experimentalDecorators` option. For more information on the available properties see the [TypeScript compiler options](https://www.typescriptlang.org/docs/handbook/compiler-options.html) documentation.
102
103## Path aliases
104
105> Available in SDK 49 and higher.
106
107In SDK 49 projects, you'll need to enable path aliases in the project's [app config](/workflow/configuration/):
108
109```json app.json
110{
111  "expo": {
112    "experiments": {
113      "tsconfigPaths": true
114    }
115  }
116}
117```
118
119Expo 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.
120
121For example, if you have a file at **src/components/Button.tsx** and wish to import it using the alias **@/components/Button** as follows:
122
123```tsx
124import Button from '@/components/Button';
125```
126
127Then simply add the alias **@/\*** in the project's **tsconfig.json** and set it to the **src** directory:
128
129```json tsconfig.json
130{
131  "compilerOptions": {
132    "baseUrl": ".",
133    "paths": {
134      "@/*": ["src/*"]
135    }
136  }
137}
138```
139
140Consider the following when using path aliases:
141
142- Restart Expo CLI after changing **tsconfig.json** to update path aliases. You don't need to clear the Metro cache when the aliases change.
143- If not using TypeScript, **jsconfig.json** can serve as an alternative to **tsconfig.json**.
144- Path aliases add additional resolution time when defined.
145- Path aliases are only supported by Metro (including Metro web) and not by `@expo/webpack-config`.
146- Bare projects require additional setup for this feature. See the [versioned Metro setup guide](/versions/latest/config/metro#bare-workflow-setup) for more information.
147
148## Absolute imports
149
150> Available in SDK 49 and higher.
151
152In SDK 49 projects, you'll need to enable absolute imports in the project's [app config](/workflow/configuration/):
153
154```json app.json
155{
156  "expo": {
157    "experiments": {
158      "tsconfigPaths": true
159    }
160  }
161}
162```
163
164Absolute imports from the project root directory are enabled automatically when the project contains a **tsconfig.json** or **jsconfig.json** file. For example:
165
166```tsx
167import Button from 'src/components/Button';
168// Imports `<project root>/src/components/Button`
169```
170
171You can modify the base directory in the tsconfig.json (or jsconfig.json) using the [baseUrl](https://www.typescriptlang.org/docs/handbook/module-resolution.html#base-url) option:
172
173```json tsconfig.json
174{
175  "compilerOptions": {
176    "baseUrl": "src"
177  }
178}
179```
180
181Consider the following when using absolute imports:
182
183- [`compilerOptions.baseUrl`](https://www.typescriptlang.org/docs/handbook/module-resolution.html#base-url) is automatically set to `.` when the `tsconfig.json` or **jsconfig.json** file exists.
184- Absolute imports in Node modules cannot be overwritten by absolute imports, as they take precedence.
185- Restarting Expo CLI is necessary to update [`compilerOptions.baseUrl`](https://www.typescriptlang.org/docs/handbook/module-resolution.html#base-url) after modifying **the tsconfig.json**.
186- If not using TypeScript, **jsconfig.json** can serve as an alternative to **tsconfig.json**.
187- Absolute imports are only supported by Metro (including Metro web) and not by `@expo/webpack-config`.
188- Bare projects require additional setup for this feature. See the [versioned Metro setup guide](/versions/latest/config/metro#bare-workflow-setup) for more information.
189
190## TypeScript for config files
191
192If you want to use TypeScript for configuration files such as **webpack.config.js**, **metro.config.js**, or **app.config.js**, additional setup is needed. You can utilize the [`ts-node` require hook](https://github.com/TypeStrong/ts-node#programmatic) to import TypeScript files within your JS config file, allowing TypeScript imports while keeping the root file as JavaScript.
193
194<Tabs>
195<Tab label="npm">
196
197<Terminal cmd={['$ npm install ts-node typescript --save-dev']} />
198
199</Tab>
200
201<Tab label="yarn">
202
203<Terminal cmd={['$ yarn add -D ts-node typescript']} />
204
205</Tab>
206</Tabs>
207
208### webpack.config.js
209
210> Install the `@expo/webpack-config` package.
211
212```js webpack.config.js
213require('ts-node/register');
214module.exports = require('./webpack.config.ts');
215```
216
217```ts webpack.config.ts
218import createExpoWebpackConfigAsync from '@expo/webpack-config/webpack';
219import { Arguments, Environment } from '@expo/webpack-config/webpack/types';
220
221module.exports = async function (env: Environment, argv: Arguments) {
222  const config = await createExpoWebpackConfigAsync(env, argv);
223  // Customize the config before returning it.
224  return config;
225};
226```
227
228### metro.config.js
229
230```js metro.config.js
231require('ts-node/register');
232module.exports = require('./metro.config.ts');
233```
234
235```ts metro.config.ts
236import { getDefaultConfig } from 'expo/metro-config';
237
238const config = getDefaultConfig(__dirname);
239
240module.exports = config;
241```
242
243### app.config.js
244
245**app.config.ts** is supported by default. However, it doesn't support external TypeScript modules, or **tsconfig.json** customization. You can use the following approach to get a more comprehensive TypeScript setup:
246
247```js app.config.js
248require('ts-node/register');
249module.exports = require('./app.config.ts');
250```
251
252```ts app.config.ts
253import { ExpoConfig } from 'expo/config';
254
255// In SDK 46 and lower, use the following import instead:
256// import { ExpoConfig } from '@expo/config-types';
257
258const config: ExpoConfig = {
259  name: 'my-app',
260  slug: 'my-app',
261};
262
263export default config;
264```
265
266## Learn how to use TypeScript
267
268A good place to start learning TypeScript is the official [TypeScript Handbook](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html).
269
270**For TypeScript and React components,** we recommend 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.
271
272</TabsGroup>
273