If you’re reading this article, big change you are a developer using Typescript. Probably you are loving the development experience of TypeScript (like me), and want to use TypeScript with WordPress.

Most of the scripts written for WordPress use plain JavaScript, jQuery or React (both frameworks that use JavaScript). TypeScript is not so common (yet), but it is possible. In this article, I will explain how. You can also watch the below video, in which I code a basic setup for WordPress and TypeScript.

And if you’re not yet familiar with TypeScript, read on with the introduction hereafter.

What is TypeScript?

TypeScript with WordPress - What is TypeScript?
The TypeScript Introduction

TypeScript is a programming language, originally developed by Microsoft. In their own words, it is JavaScript with syntax for types.

But what does that mean? You may be familiar with JavaScript, the programming language that runs a lot of the software on the web and is also used in WordPress a lot.

TypeScript is in the end very similar to JavaScript, and it actually compiles to JavaScript for use in production. But during development, it adds a lot of functionalities that make development a lot easier. Especially if you’re going to use a lot of JavaScript, using TypeScript instead may be a very good choice.

The most important aspect of TypeScript is that it is strongly typed, and it adds support for ‘types’ in JavaScript.

Strongly Typed and Types

The term strongly typed basically means that a variable can not be of another type other than how it was declared.

For example, a variable that is declared as a number, can not suddenly be a string (which is possible in plain JavaScript). Now many programming languages are strongly typed, and this prevents a lot of bugs from happening. But JavaScript isn’t. And that’s where TypeScript enters the party.

JavaScript versus TypeScript

So what is the difference? Let’s look at two examples, in plain JavaScript and in TypeScript.

Plain Javascript

function addNumber(a, b) {
  return a + b;
}

console.log( addNumber(4, 5) ); // This outputs: 9
console.log( addNumber(4, '5') ) // Woops! this outputs: 45

The above example makes clear that JavaScript is dynamically typed. In the addNumber function, we would expect two numbers as an argument. However, we can still enter a number and a string, or even two strings. On the fly, javascript adds the two values and converts it to a string, which means the value that is returned is a string of ‘a + b’. In the example, ‘4’ + ‘5’, which is 45.

Of course, we can use JavaScript functions such as parseFloat or parseInt to force variables to be a number or write an if statement to check for numbers.

But this is quite tedious to do, especially if you are working with complex variables and arguments, such as large objects. TypeScript makes it a lot easier.

TypeScript

Enter the following example – the same as above, but in TypeScript.

function addNumber(a: number, b: number): number {
  return a + b;
}

console.log( addNumber(4, 5) ); // This outputs: 9
console.log( addNumber(4, '5') ) // The editor will give an error and this will not compile.

And the above example directly demonstrates the power of TypeScript. In the example above, I clearly indicated that for both arguments (a and b), it expects to be a number, and the function also expects to return a number.

Hence, adding a string in the function will give an error. By the way, a TypeScript file usually has the .ts file extension.

Installing TypeScript

To use TypeScript, you need to install it as a dev-dependency using npm, the package manager for node and run the compiler in the command line. I assume you are familiar with using npm, which comes available on every machine that has NodeJS installed.

If you are not, these are the basic steps you need to create, in the command line of your editor:

// In the folder of your project
npm install typescript --save-dev

// Instead, you can also install TypeScript globally
npm install -g typescript

After these steps, create a file in the root of your project, such as script.ts. Start writing TypeScript in this file. Compiling is easy:

// Compile the file from TypeScript to plain JS using the following command
tsc script.ts

To modify any settings for the TypeScript compiler and type linter, you can also add a tsconfig.json at the root of your project (which is a topic in itself). You can also discover more at the official site of TypeScript.

The Story of TypeScript

And if you want to know more about the story of TypeScript, this amazing video explains it all.

Advantages of using TypeScript with WordPress

Although TypeScript may seem more complex to implement with WordPress, it has a lot of advantages. Let’s discuss a few:

  • TypeScript prevents bugs and errors happening, because you define what types you expect.
  • During development, the code editor will automatically give error messages if something is different that aspected. Assigning a string to a variable that is a number? You will get an error. Acccessing an object property that doesn’t exist? You’ll get an error message in the editor. And that saves a lot of headaches before your code goes live.
  • TypeScript adds auto-completion to many aspects in your code editor, which makes the developing experiences very smooth. Especially if you would have been using a lot of JavaScript (or TypeScript) files, classes, models and so forth.
  • TypeScript makes it also a lot easier to work with classes.

For WordPress, there is a drawback though. Many popular packages that are written in JavaScript also provide support for TypeScript, by providing custom types that belong in these packages. Unfortunately, WordPress does not have support for many of its types yet (which come in especially useful if you are developing new blocks for the Gutenberg Editor).

But enough explanations for now. How do you actually set up TypeScript in WordPress?

Using TypeScript with WordPress

WordPress with TypeScript
Let’s get WordPress with TypeScript

TypeScript can be used with WordPress, but it’s not a plug and play solution. In this example, I will be creating an empty plugin that incorporates TypeScript.

I am using Visual Studio Code as my editor, a great editor that has built-in support for TypeScript. I also use Local, which is one of the best tools for developing WordPress locally. I assume you’re also developing locally.

Initial Steps

First, move to the plugin folder of your WordPress installation and create a new folder with any plugin name. We’re going to work in this folder.

1. Initialize your package.json by running the following command:

npm init

Follow the wizard according to what you need.

2. Now, install TypeScript as a dev-dependency. In your command line:

npm install typescript --save-dev

3. We’re also going to use @wordpress/scripts. This module from WordPress makes it very easy to bundle your JavaScript and SCSS files, and as we will see, even TS files. In your command line:

npm install @wordpresss/scripts --save-dev

4. To make @wordpress/scripts work correctly with TypeScript, we need to add ts-loader as a dev-dependency too. But we’re not there yet!

npm install ts-loader --save-dev

There is also a useful shorthand to install all 3 packages as devDependencies at once:

npm i -D ts-loader typescript @wordpress/scripts

File Structure

We need to create some additional files, such as index.php (the entry point for your plugin), tsconfig.json and webpack.config.js. And obviously, the TypeScript file we are going to use. This is the file structure I used:

How to Use TypeScript in WordPress: the Starters Guide. 1
My set-up for TypeScript and WordPress (the public folder is generated after compiling).

File Contents

Let’s briefly walk through each of these files and see what contents they should have (we’ll skip the readme and .gitignore files, which are not strictly needed).

1. package.json

The majority of the package.json contents was set up when you initialized npm and set up the dependencies.

Two scrips are added, that use the @wordpress/scripts module: ‘wp-scripts build’ and ‘wp-scripts start’. These respectively compile the code for production use, or start up the compiler in watch mode, useful during development. We’ll discover more about this in the webpack.config.js file.

{
    "name": "wp-typescript-starter",
    "version": "1.0.0",
    "author": "Michiel Tramper",
    "description": "A starter package for using TypeScript with WordPress",
    "devDependencies": {
        "@wordpress/scripts": "latest",
        "ts-loader": "latest",
        "typescript": "latest"
    },
    "scripts": {
        "build": "wp-scripts build",
        "start": "wp-scripts start"
    }
}

2. webpack.config.js

Because we use @wordpress/scripts as a dev-dependency, we can use commands such as wp-scripts build and wp-script start to start compiling and bundling scripts. Under the hood, this uses Webpack as its module bundler, which is I believe the most used bundler for bundling scripts. And that’s why we need to add a webpack.config.js to the root of our project, so we can modify its settings.

To make it work with TypeScript, we need to expand the configuration:

const path = require('path');
const defaults = require('@wordpress/scripts/config/webpack.config.js');

module.exports = {
  ...defaults,
  entry: {
    scripts: path.resolve( process.cwd(), 'assets/src', 'scripts.ts' )
  },
  output: {
    filename: '[name].js',
    path: path.resolve( process.cwd(), 'assets/public' ),
  },  
  module: {
    ...defaults.module,
    rules: [
      ...defaults.module.rules,
      {
        test: /\.tsx?$/,
        use: [
          {
            loader: 'ts-loader',
            options: {
              configFile: 'tsconfig.json',
              transpileOnly: true,
            }
          }
        ]        
      }
    ]
  },
  resolve: {
    extensions: [ '.ts', '.tsx', ...(defaults.resolve ? defaults.resolve.extensions || ['.js', '.jsx'] : [])]
  }
};

As you can see, this script still takes the configurations from @wordpress/scripts by importing them, and destructuring the important ones. But some additional configurations are added.

In the above configuration, I changed the default entry point. It’s now our TypeScript file placed in /assets/src/scripts.ts. I output the compiled script to /assets/public/[name-of-script].js.

Secondly, I added some extra rules to handle the loading of .ts and .tsx files (the TypeScript version of .jsx files, the format often used in React files). The dev-dependency ts-loader will handle these files, and these rules make sure TypeScript can be properly loaded and resolved.

3. tsconfig.json

In this file, you can specify any TypeScript settings for the given project. This is the setup I used:

{
  "compilerOptions": {
      "outDir": "./assets/public/",
      "jsx": "react-jsx",
      "module": "ESNext",
      "target": "ES2015", // Set to ES5 for older browser support.
      "strict": true,
      "allowSyntheticDefaultImports": true,
      "moduleResolution": "node"
  }
}

I won’t go into further detail, but the TSConfig Reference can be found here.

4. index.php

This is the starting point for our plugin, and also makes WordPress recognize our file as a plugin. It’s just a regular plugin setup but also enqueues our compiled script.

<?php
/**
 * Plugin Name: Your Plugin Name 
 * Description: Starter file for creating plugins and themes with TypeScript and WordPress.
 * Version: 1.0.0
 * Author: Enter Your Author Name
 * License: GPL3
 * License URI: https://www.gnu.org/licenses/gpl-3.0.html
 *
 * PHP Entry point for TypeScript starter template
 * This function enqueues the given script at the front-end of WordPress
 * 
 * If you want to enqueue your assets for the block editor, use the 'enqueue_block_editor_assets' action instead
 */
add_action('wp_enqueue_scripts', function(): void {
  
  // When used in a WordPress theme (place this file in functions.php of your theme)
  // $script_args = include( get_template_directory() . '/assets/public/scripts.asset.php');
  // wp_enqueue_script('wp-typescript', get_template_directory_uri() . '/assets/public/scripts.js', $script_args['dependencies'], $script_args['version'] ); 
  
  // When used in a WordPress plugin
  $script_args = include( plugin_dir_path( __FILE__ ) . 'assets/public/scripts.asset.php');
  wp_enqueue_script('wp-typescript', plugins_url('assets/public/scripts.js', __FILE__), $script_args['dependencies'], $script_args['version']);
});

Please note that it includes a PHP script that is generated after you run either ‘npm run build’ or ‘npm run watch’. This runs the wp-scripts script, which also generates a PHP script that automatically includes all dependencies for the given project.

The latter is really useful when you are using any of the packages provided by WordPress. Just import them in your scripts using the default ES6 import syntax, and the running script will automatically update the enqueued assets. This makes sure the correct scripts are enqueued.

5. assets/src/scripts.ts

Needlessly, you also need to add the actual TypeScript file. It could contain anything you like.

And you’re done! With this setup, you should be able to develop your next theme or plugin with TypeScript and PHP.

TypeScript Starter Template for WordPress

If you want to skip the above, I added a useful starter template for using TypeScript with WordPress. You can find the GitHub repository here. Just clone it and you are good to go.

Happy TypeScripting! Let’s make WordPress work with TypeScript.