# TypeScript support
🚧 TypeScript documentation
This section is still a work in progress and will continue to be updated and improved. Migrating existing Strapi applications written in JavaScript is not currently recommended. In the meantime, feel free to ask for help on the forum (opens new window) or on the community Discord (opens new window).
TypeScript adds an additional type system layer above JavaScript, which means that existing JavaScript code is also TypeScript code. Strapi supports TypeScript in new and existing projects running v4.2.0 and above. The core Developer Documentation contains code snippets in both JavaScript and TypeScript.
# Create a new TypeScript project
Create a Strapi project with Typescript support by using the --ts or --typescript flags with either the npm or yarn package manager.
💡 TIP
Adding the --quickstart flag in addition to the --ts flag will create a TypeScript project with an SQLite database.
# Understand TypeScript support
TypeScript-enabled Strapi applications have a dist directory at the project root and 2 tsconfig.json files (see project structure).
| TypeScript-Specific directories and files | Purpose | Location |
|---|---|---|
./dist directory | Adds the location for compiling the project JavaScript source code. | application root |
build directory | Contains the compiled administration panel JavaScript source code. The directory is created on the first yarn build or npm run build command | ./dist/ |
tsconfig.json file | Manages TypeScript compilation for the server. | application root |
tsconfig.json file | Manages TypeScript compilation for the admin panel. | ./src/admin/ |
Starting the development environment for a TypeScript-enabled project requires building the admin panel prior to starting the server. In development mode, the application source code is compiled to the ./dist/build directory and recompiled with each change in the Content-type Builder. To start the application run the following commands in the application root directory:
# Use TypeScript typings
To leverage your experience while using TypeScript Strapi comes with typings on the Strapi class.

# Develop a plugin using TypeScript
New plugins can be generated following the plugins development documentation. There are 2 important distinctions for TypeScript applications:
- After creating the plugin, run
yarn installornpm run installin the plugin directorysrc/admin/plugins/[my-plugin-name]to install the dependencies for the plugin. - Run
yarn buildornpm run buildin the plugin directorysrc/admin/plugins/[my-plugin-name]to build the admin panel including the plugin.
✏️ NOTE
It is not necessary to repeat the yarn install or npm run install command after the initial installation. The yarn build or npm run build command is necessary to implement any plugin development that affects the admin panel.
# Start Strapi programmatically
Initiating Strapi programmatically in a Typescript project requires additional configurations to load everything correctly.
# Understand programatic use
When initiating Strapi programmatically using the default export of @strapi/strapi, you can pass different parameters, among them there is the app directory and the dist directory. The app directory is the project root directory and dist is a subdirectory of app which contains all of the compiled code.
Basically, the dist directory represents the compiled project (with the same folder structure as the app directory) and the app directory represents your codebase (TS or JS). The main differences are:
- When using the Content-type Builder to create/update/delete content types (or any other service that creates files), Strapi uses the
appfolder to write the files. - When reading what content types exist on the system, Strapi reads the
distfolder. Basically, we're reading from the dist directory & writing to the app directory. - Only the app folder is watched when using the develop command. In TS, a compilation will be triggered when a change is detected in the app folder & the output will be written to the dist folder
::: Note
- The public folder is considered static and thus ignores app/dist directories.
- When developing in vanilla JS, the
distfolder will be the same as the app folder since we writing & reading in the same place. If we were to use some kind of compilation tool for JS (babel, etc...) we would set thedistdirectory to wherever babel output the code.
:::
The default values for the app & dist directories are transformed and assigned using the following behavior:
const resolveWorkingDirectories = opts => {
const cwd = process.cwd();
const appDir = opts.appDir ? path.resolve(cwd, opts.appDir) : cwd;
const distDir = opts.distDir ? path.resolve(cwd, opts.distDir) : appDir;
return { appDir, distDir };
}
# Handle both JavaScript and TypeScript codebases when starting Strapi programmatically
This can be particularly useful when creating CLI tools or developing a plugin. To do so, you can use the @strapi/typescript-utils package:
const tsUtils = require('@strapi/typescript-utils');
const strapi = require('@strapi/strapi');
const appDir = process.cwd();
// Automatically detect if this is a project using Typescript
const isTSProject = await tsUtils.isUsingTypeScript(appDir);
// Resolve the directory containing the compilation output
const outDir = await tsUtils.resolveOutDir(appDir);
if (isTSProject) {
// If we're in a Typescript project, compile the TS code in appDir
await tsUtils.compile(appDir, {
watch: false,
configOptions: { options: { incremental: true } },
});
}
// If we're in a Typescript project, use a custom dist
// directory, otherwise set it to appDir value
const distDir = isTSProject ? outDir : appDir;
// Start the app by providing the app and dist directories
const app = await strapi({ appDir, distDir }).load();