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