Strapi v4.2.0 second beta for TypeScript support

Strapi 4.2.0-beta.1 Release


Second beta for TypeScript support

Hello everyone, as the title suggests, we just released the second iteration concerning the TypeScript support for Strapi. You can find it under the 4.2.0-beta.1 version tag.

Here’s a list of the notable changes & what’s coming next.

:tada: What’s New

TL;DR:

🪲

  • Fix Documentation Plugin TS integration
  • Fix Upload Plugin TS integration
  • Fix local plugin paths

:rocket:

  • Allow extending the StrapiInterface from user app
  • Replaced tsconfig-admin.json & tsconfig-server.json by tsconfig.json files in different directories
  • App and local plugins builds have been decoupled
  • Added anonymous telemetry properties to measure Typescript usage and adoption
  • TS Telemetry

:rocket: Strapi Interface Extension

In the previous release (4.2.0-beta.1) we were exporting a Strapi type that we were using to type the global strapi variable (it was also meant to be used by the community to extend it).

However, some users were struggling to extend this type to include their definitions in the main interface.

After discussing it a bit, we were hesitating between removing all the existing Strapi types (as we are going to redo them shortly anyway) or just exposing the StrapiInterface so that it can be extended by the users. In the end, we decided to move forward with the second option.

You can now extend the Strapi interface by doing the following:

 /// ./index.d.ts

import '@strapi/strapi';

declare module '@strapi/strapi' {
	interface StrapiInterface {
		foo: string;
	}
}

/// ./src/index.ts

import { Strapi } from '@strapi/strapi';

export default {
  register({ strapi }: { strapi: Strapi }) {
		strapi.foo // it shouldn't raise an error + trigger autocomplete  },

  bootstrap(/*{ strapi }*/) {},
};

strapi.foo // it shouldn't raise an error + trigger autocomplete

Note: Please note that TypeScript will only allows you to extend the interface, not change the type of existing properties of the interface.

:rocket: tsconfig.json Files

In the first TS support beta release, we added two configuration files to the application:

  • ./tsconfig-admin.json
  • ./tsconfig-server.json

It caused issues as some IDEs were not able to pick up the files and apply the correct IntelliSense rules.

Also, after further consideration, we decided it wasn’t making sense to have a tsconfig-admin.json file int the root directory as the admin code is located in the src/admin directory only.

Thus, with this beta release, the tsconfig.json files will be generated in the following locations:

  • ./tsconfig.json
  • ./src/admin/tsconfig.json

They’ll both extend template configurations (one for the admin, one for the server), and you’ll be able to modify any rule you want.

:rocket: TypeScript Plugins

When we released the first TS support beta, we decided to couple the build of all local plugins files in the application build. While it saved time, it broke local plugin paths and forced the plugins to be coupled to the application.

In this release, we’ve decided to revert this coupling for the server while keeping it for the admin.

Why? Because as of today, the admin build needs to include all the files and the logic that will be present in the final build. It means that we cannot load plugins admin builds dynamically on startup.

Thus, we’re adding one tsconfig.json file and scripts in the local plugins package.json files.

  • The tsconfig.json file will extend the one from @strapi/typescript-utils
  • The scripts are going to be build and develop, and will use basic tsc commands for now. We’ll update them with our compilers if we need them.

:rocket: Telemetry

To measure the adoption/usage of the TypeScript support and spot eventual bugs, we’ve decided to add some properties to the anonymous analytics events we’re collecting.

  • useTypescriptOnServer: boolean → Simply check if the ./tsconfig.json file exists
  • useTypescriptOnAdmin: boolean → Simply check if the ./src/admin/tsconfig.json file exists

🪲 Upload Plugin Fix

In the previous beta release, the upload plugin duplicated the public folder (and basically every file too) and kept one copy both in the app and dist directory. It was causing issues when uploading/reading files and caused a huge performance drop for large amounts of files.

In this new release, we’re adding a new static directory layer to hold the public directory in one place.

tl;dr: the public directory is no longer duplicated and lives in strapi.dirs.static.public

🪲 Documentation Plugin Fix

In the previous beta release, the documentation plugin was trying to read the extensions & configuration files/schemas directly from the dist folder. However, those files were not copied automatically to the dist folder upon generation (since they are not handled by the TypeScript compiler).

We’re now reading the documentation configuration files & schemas directly from the app directory to solve this issue.

🪲 Fix Local Plugins Paths

See: :rocket: TypeScript Plugins

:eyes: What’s coming?

In the next TS releases we would like to:

  • Listen to the community feedback on the first few releases & implement changes when needed
  • Release better documentation when creating a project with TypeScript
  • Fix all the CLIs commands that are not working with TS
  • Add typings to the Strapi global object (it’s going to be a long one and we’ll probably release new improvements in each release)
  • Fix issues/documentation linked to unit testing and programmatic Strapi instances.
  • Automatic types generation for local content types, controllers, plugins, service,s and routes (probably multiple iterations as we’ll have to deal with complex logic here)
  • JS to TS project conversion

Have a nice day!

4 Likes

Not sure if Im missing something but when I go to the strapi repo there isn’t a 4.2.0-beta.1 tag

The 4.2.0-beta.1 version is released under the beta tag, so you just have to use npx create-strapi-app@beta my_project --ts
You can have more information about our tags & package metadata by running npm show @strapi/strapi or npm dist-tags @strapi/strapi

npx create-strapi-app@beta my_project --ts

throws error: unknown option ‘–ts’ on ubuntu 22.04. Had even tried with --typescript option but in vain

@agahebeye
Could you please try again? I think that for 1 or 2 days another feature took the beta tag (thus didn’t reference the TS beta).
Also, if it still doesn’t work, please try using npx create-strapi-app@4.2.0-beta.2 my_project --ts

We are using strapi 3.6.0 but constantly getting 502 bad gateway error

So I am trying to use the Strapi type as shown here:

export default {
  register({ strapi }: { strapi: Strapi }) {
		const service = strapi.service('some uid');
  },
  bootstrap(/*{ strapi }*/) {},
};

But the ts compiler complains that the StrapiInterface does not have the property service, which doesn’t make any sense, because the code is running if the type is set to any first.

src/index.ts:27:34 - error TS2339: Property 'service' does not exist on type 'StrapiInterface'.

27     const service = strapi.service('api::data.cache');

This confuses me a bit especially after looking into the type definition and it literally extends the Strapi class defined in the Strapi.js file which clearly has the service member.
For some reason when the StrapiInterface extends the Strapi class, all super properties are getting lost and only the newly defined properties (‘query’ and ‘entityService’) are defined.

Any thoughts?