Build an API with Node.js, Express, and TypeScript
Tags: code, javascript, node
Published: 2021-03-19 17:26:09

---
title: Build an API with Node.js, Express, and TypeScript
published: true
date: 2021-02-24 14:05:00 UTC
tags: Code,javascript,nodejs
canonical_url: https://www.split.io/blog/node-js-typescript-express-tutorial/
---

A RESTful API in JavaScript can be built from scratch very quickly. It usually means using a Node.js environment and a server run by the Express library. One could argue that a downside of such a technical stack would be the lack of types – the fact that JavaScript isn’t a strongly typed language. But you can instantly stop worrying and learn to love JavaScript, well, actually – love TypeScript – JavaScript’s type-safe superset and an excellent tool for a better and safer development experience.

Let’s run quickly over the topics of this tutorial:

- Creating an Express-driven Node.js application exposing a REST API
- Making the application code strongly typed with TypeScript
- Adding new feature using [feature flag branching](https://www.split.io/blog/branch-by-abstraction/) (branch by abstraction) with Split
- Testing the configured percentage split

Wondering what the app’ll be about? Do the time zones of the world sound interesting enough? Let’s get started!

## Prerequisites for Node and TypeScript

For the best experience inside this tutorial, you need to have:

- Basic knowledge of Node.js and Express
- Basic familiarity with the command line
- Node.js and npm installed
- A [Split](https://app.split.io/) account

If you want to follow along by inspecting the codebase while reading the next sections, the full code example is available on a [splitio-examples GitHub repo](https://github.com/splitio-examples/split-nodejs-postgres-example).

## Set Up Your TypeScript Development Environment

You’ll start by creating a project directory and move to its root folder:

```

`mkdir node-typescript
cd node-typescript`
<small id="shcb-language-1"><span>Code language:</span> <span>Bash</span> <span>(</span><span>bash</span><span>)</span></small>
```

Start the `npm` project by running `npm init`, creating a `package.json` file. As an alternative, you can copy the following JSON structure to the `package.json` that you’ll make on your own:

```

`{
  "name": "node-typescript-api",
  "version": "1.0.0",
  "description": "Build an App with Node.js, Express, and TypeScript",
  "main": "index.js",
  "scripts": {},
  "license": "MIT"
}`
<small id="shcb-language-2"><span>Code language:</span> <span>JSON / JSON with Comments</span> <span>(</span><span>json</span><span>)</span></small>
```

If you plan to use TypeScript in your application, it’s best to hook it up at the very beginning, as TypeScript will provide useful development features while you code. Not surprisingly, it is installed as an npm package called `typescript`, and here you’ll install yet another one – `ts-node`:

```

`npm i -D typescript ts-node`
<small id="shcb-language-3"><span>Code language:</span> <span>Matlab</span> <span>(</span><span>matlab</span><span>)</span></small>
```

`typescript` package is the key library in all the applications using TypeScript inside the codebase. It transforms the TypeScript code to JavaScript in a process called transcompiling or _transpiling_. The subtle difference from the term _compiling_ exists, as compiling defines code transformation from a high-level programming language to a low-level one. At the same time, transpiling is the term used for code transformation between high-level languages. However, in TypeScript ecosystem(s), you’ll probably run into both terms.

`ts-node` is a useful package that enables running TypeScript files (ones having the `.ts` extension) from the command line within the Node environments.

The `-D`, also known as `--dev`, means that both packages should be installed as _development dependencies_. After the installation, you’ll find the `devDependencies` property inside the `package.json` populated with these packages.

> Node environment (or browser environment in any client-side app) still only understands the JavaScript language. The TypeScript code needs to be transpiled to JavaScript **before the package is used in runtime**. If someone were using your app as an npm package, he wouldn’t need to install the `typescript` dependency, as that person would only use the runtime version of the application/package. For that reason, `typescript` is a development dependency.

Next, create a `tsconfig.json` file in the project’s root folder. The presence of a `tsconfig.json` file in a directory indicates that the directory is the root of a TypeScript project. Also, this file allows you to configure how the `typescript` library will compile the TypeScript code inside the project. Populate the file with the following JSON:

```

`{
  "compilerOptions": {
    "module": "commonjs",
    "target": "es6",
    "rootDir": "./",
    "esModuleInterop": true
  }
}`
<small id="shcb-language-4"><span>Code language:</span> <span>JSON / JSON with Comments</span> <span>(</span><span>json</span><span>)</span></small>
```

The crucial property of the configuration file is called `compilerOptions`. Options set here define most of the TypeScript configuration. Let’s cover some of the basic ones.

- `module` specifies a module system to be used in the compiled JavaScript code. The standard module system inside a Node environment would be CommonJS.
- `target` property defines the targeted JavaScript version of the compiled code. Since the code is supposed to run on your server, inside a Node environment, the ES6 JavaScript version is good to go. But, if this was a client-side app that runs in, e.g., Internet Explorer browser, then you should aim for lower ECMAScript versions and have something like `"target": "es5"`.
- `rootDir` defines the root location of typescript files inside the project. It doesn’t necessarily need to be the root of the project folder, like here.
- `esModuleInterop` flag enables default imports for TypeScript modules with `export =` syntax that you’ll need for importing from the Express library later on.

Bear in mind that this basic set of `tsconfig.json` options is just something to get you started. TypeScript and its compiler are highly configurable, and there is a lot more to learn about it. Feel free to explore the [TypeScript docs](https://www.typescriptlang.org/docs) for more information.

### What Are Declaration Files in TypeScript?

Declaration files describe types of various JavaScript APIs to the TypeScript compiler. In your project, you’ll be defining your own types, but you’ll also need types for various Node APIs or different external packages that you’ll be using, like Express. These files often come with the `.d.ts` extension. They are used for TypeScript [module resolution](https://www.typescriptlang.org/docs/handbook/module-resolution.html#how-typescript-resolves-modules). Those files are modules that don’t have any code implementation inside but serve as a layer that describes the JavaScript implementation behind it by its type.

Some external JavaScript libraries have the TypeScript declaration files shipped within the npm package (like the one you’ll use later on – `@splitsoftware/splitio`). In contrast, the other declaration files need to be installed as a separate package that usually comes with a `@types` namespace prefix, provided by the [DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped) project. Node APIs type definitions also need to be fetched from the `@types` namespace, so let’s first install the `@types/node` package as a development dependency:

```

`npm i -D @types/node`
<small id="shcb-language-5"><span>Code language:</span> <span>CSS</span> <span>(</span><span>css</span><span>)</span></small>
```

## Build an Express Server in Node

The next thing you’d need is to install Express.js, a popular package to create a server in Node.

```

`npm i express`
<small id="shcb-language-6"><span>Code language:</span> <span>Matlab</span> <span>(</span><span>matlab</span><span>)</span></small>
```

With the TypeScript context in mind, let’s also install the types for Express as a development dependency:

```

`npm i -D @types/express`
<small id="shcb-language-7"><span>Code language:</span> <span>CSS</span> <span>(</span><span>css</span><span>)</span></small>
```

In the root directory, create an `app.ts` where the server application will run:

```

`import express from 'express';

const app = express();
const port = 3000;

app.listen(port, () => {
  console.log(`Timezones by location application is running on port ${port}.`);
});`
<small id="shcb-language-8"><span>Code language:</span> <span>JavaScript</span> <span>(</span><span>javascript</span><span>)</span></small>
```

The `express` module is required to create a server. With this configuration, the server will run on port `3000`, with the base URL where the application runs being `http://localhost:3000`.

Install the utility package Nodemon, which will speed up your development by automatically restarting the server after each change. Nodemon is also installed as a development dependency, as you only need it during the development phase.

```

`npm i -D nodemon`
<small id="shcb-language-9"><span>Code language:</span> <span>Matlab</span> <span>(</span><span>matlab</span><span>)</span></small>
```

In the `package.json` file, inside the `scripts` property, add a script named `serve` with `nodemon app.ts` command that will be used to start the server. Remember, the `ts-node` package makes this possible under the hood, as normally you wouldn’t be able to start typescript files from the command line.

```

`...
"scripts": {
    "serve": "nodemon app.ts"
  }
...`
<small id="shcb-language-10"><span>Code language:</span> <span>Bash</span> <span>(</span><span>bash</span><span>)</span></small>
```

Now you can start your server by simply running:

```

`npm run serve`
<small id="shcb-language-11"><span>Code language:</span> <span>Arduino</span> <span>(</span><span>arduino</span><span>)</span></small>
```

The following should appear in the terminal:

![Node TypeScript tutorial screenshot: nodemon in terminal after npm run serve.](https://www.split.io/wp-content/uploads/2021/02/nodetypescript-01-nodemon-1024x223.png?width=1024)

Alternatively and without Nodemon, you could run the server with `npx ts-node app.ts`.

## Add an Endpoint inside the Node Server

Change the `import` statement on the first line, so you also import the TypeScript _interfaces_ that will be used for `request`, `response`, and `next` parameters inside the Express middleware.

```

`import express, { Request, Response, NextFunction } from 'express';`
<small id="shcb-language-12"><span>Code language:</span> <span>JavaScript</span> <span>(</span><span>javascript</span><span>)</span></small>
```

As mentioned, this application will be all about the time zones of the world. The REST API will have a single `GET /timezones` endpoint, which will return the hardcoded list of locations with a timezone name, abbreviation, and the UTC offset. Since there is only one route, let’s just put it inside `app.ts`, by adding this code:

```

`interface LocationWithTimezone {
  location: string;
  timezoneName: string;
  timezoneAbbr: string;
  utcOffset: number;
};

const getLocationsWithTimezones = (request: Request, response: Response, next: NextFunction) => {
  let locations: LocationWithTimezone[] = [
    {
      location: 'Germany',
      timezoneName: 'Central European Time',
      timezoneAbbr: 'CET',
      utcOffset: 1
    },
    {
      location: 'China',
      timezoneName: 'China Standard Time',
      timezoneAbbr: 'CST',
      utcOffset: 8
    },
    {
      location: 'Argentina',
      timezoneName: 'Argentina Time',
      timezoneAbbr: 'ART',
      utcOffset: -3
    },
    {
      location: 'Japan',
      timezoneName: 'Japan Standard Time',
      timezoneAbbr: 'JST',
      utcOffset: 9
    }
  ];

  response.status(200).json(locations);
};

app.get('/timezones', getLocationsWithTimezones);`
<small id="shcb-language-13"><span>Code language:</span> <span>C#</span> <span>(</span><span>cs</span><span>)</span></small>
```

> Hardcoded in-memory data is something you’ll be using inside this example. In a real-world app, you’ll want to replace the hardcoded data with the one stored in a database.

Notice how this endpoint returns a list of locations with a type `LocationWithTimezone` you just easily defined using a TypeScript interface. There is no conceptual difference between this type you made yourself or any other type, e.g., the one imported from an external declaration file. They both present the same TypeScript mechanism to describe a JavaScript entity. To make sure this route works, you can test it against a request made with _curl_ from the terminal:

```

`curl http://localhost:3000/timezones`
<small id="shcb-language-14"><span>Code language:</span> <span>Arduino</span> <span>(</span><span>arduino</span><span>)</span></small>
```

This is the response you should see in the console:

```

`[{"location":"Germany","timezoneName":"Central European Time","timezoneAbbr":"CET","utcOffset":1},{"location":"China","timezoneName":"China Standard Time","timezoneAbbr":"CST","utcOffset":8},{"location":"Argentina","timezoneName":"Argentina Time","timezoneAbbr":"ART","utcOffset":-3},{"location":"Japan","timezoneName":"Japan Standard Time","timezoneAbbr":"JST","utcOffset":9}]`
<small id="shcb-language-15"><span>Code language:</span> <span>JSON / JSON with Comments</span> <span>(</span><span>json</span><span>)</span></small>
```

## Create a Feature Flag for Your Node + TypeScript App

Feature flags are used in numerous production applications around the world, and there is sound reasoning behind that. The natural state of living applications is that they get updated from time to time, maybe even on daily or hourly basics. Every update or every new version of the application is a potential source for a new bug to be introduced. Feature flags come in handy in those situations, as they give you the ability to serve the latest version of the application only to a specific target inside your audience first.

Inside this tutorial, the newly introduced feature, or a code update, will be a new location added to the list of locations returned by `GET /timezones` route – a warm destination in the heart of Africa, known as Kenya. You don’t want all application users to get the Kenya location’s data at first. Maybe you want to see if that data is even relevant to the users, so you’ll want to do some kind of A/B testing first – let only half of the users get the time zone information about Kenya. Let’s get started with the feature flag configuration.

To create a feature flag, you’ll need access to [Split](https://app.split.io/) application. If you don’t have a Split account yet, you should register one to continue. After you log in to Split, navigate to the **Splits** section on the left and click **Create Split**. The dialog will prompt you for the split’s name, which you can define as `timezone_split`. Leave the default settings for everything else and click **Create** to finish.

![Node TypeScript tutorial screenshot: creating the timezone_split in Split's UI.](https://www.split.io/wp-content/uploads/2021/02/nodetypescript-02-create-a-split-1024x977.png?width=1024)

You should see a newly created split with a **Staging-Default** environment preselected :

![Node TypeScript tutorial screenshot: Adding targeting rules to the Staging environment.](https://www.split.io/wp-content/uploads/2021/02/nodetypescript-03-no-targeting-rules-defined.png?width=892)

If **Prod-Default** environment is preselected, switch to **Staging-Default** by using the dropdown in the upper left corner:

![Node TypeScript tutorial screenshot: switching from production to staging environment.](https://www.split.io/wp-content/uploads/2021/02/nodetypescript-04-prod-default-pre-selected.png?width=328)

To configure the split settings, click **Add Rules**.

The state of a feature flag in Split is known as _treatment_. The most common values for treatments are `on` or `off`, but you can use anything else. As configured here in the **Define treatments** section, when the treatment is `on`, users will get a new location in the given response of the `GET /timezones` endpoint. If the treatment is `off`, the same endpoint will return the original list of locations with timezones, without Kenya.

![Node TypeScript tutorial: defining treatments in the Split UI.](https://www.split.io/wp-content/uploads/2021/02/nodetypescript-05-define-treatments-1024x239.png?width=1024)

Now, let’s set up the _targeting rules_, where you’ll define the targeted audience for this split. The split will be configured as a _percentage split_, and that kind of targeting is set up inside the **Set The Default Rule** section. Percentage split means that treatments will be randomly distributed between users in the percentage you define. As seen in the next picture, you’ll define that half of your users get the `on` treatment, leaving the other half with the `off` treatment.

![Node TypeScript tutorial: editing the Default Rule to set percentage of on vs off treatments.](https://www.split.io/wp-content/uploads/2021/02/nodetypescript-06-set-targeting-rules-1024x427.png?width=1024)

> There can be situations in which the split won’t be active in the application for various reasons, so the users will branch according to what you’ve set up inside the **Set The Default Treatment** section. A good practice here is to have the `off` treatment as the default one, as you probably don’t want new features to be accessible to everyone without being tested first.

After that, you click **Save changes** and then **Confirm** , resulting in the split settings being saved.

## Connect Your Feature Flag with Node

Back in the application code, Split Node.js SDK is needed to apply the previously set logic in the application runtime. It can be installed via npm, and it also ships with the TypeScript declaration files, so you don’t need to install a separate package for that:

```

`npm i @splitsoftware/splitio`
<small id="shcb-language-16"><span>Code language:</span> <span>CSS</span> <span>(</span><span>css</span><span>)</span></small>
```

Add the following code in the `app.ts`. Optionally, you can put the `import` statement at the top of the file.

```

`import split = require('@splitsoftware/splitio');

const factory: SplitIO.ISDK = split.SplitFactory({
  core: {
    authorizationKey: 'YOUR_API_KEY'
  }
});

const client: SplitIO.IClient = factory.client();`
<small id="shcb-language-17"><span>Code language:</span> <span>JavaScript</span> <span>(</span><span>javascript</span><span>)</span></small>
```

The API key you’ll use here is the one you can see in the **Admin Settings** of the Split dashboard. The key you search for is the second one from the – staging one for the SDK. Of course, in a production app, it is considered a good practice to store this key as an environment variable on your machine.

![Node TypeScript tutorial: visiting Admin Settings in Split to get your API key.](https://www.split.io/wp-content/uploads/2021/02/nodetypescript-07-admin-settings-keys-1024x429.png?width=1024)

> Stop for a second on the line in the previous snippet where you import from the Split library: `import split = require('@splitsoftware/splitio')`. TypeScript module provided by Split uses the `export =` syntax for exposing its members, so this kind of import is needed according to TypeScript documentation. More on that topic can be found [here](https://www.typescriptlang.org/docs/handbook/modules.html#export--and-import--require).

As SDK now communicates with the app, it can be utilized to get a respective treatment for a user’s request with the `getTreatment` method. The method receives two arguments – _key_ and _split name_. The key is often something used to identify a particular user and calculate a specific treatment for that user. Simultaneously, the split name is the identifier of the split configured in the Split dashboard.

A good idea is to put the logic for calculating the user’s treatment inside an Express middleware – a function that will be executed against each API request before proceeding further. That middleware can read the user’s authentication data, e.g., the data stored in the `authorization` header, and use it as a key for the `getTreatment` method. The second argument is the name of the previously configured split (`timezone_split`).

> In the live application, you’d want to have a more robust authentication mechanism to identify your users, but here we’ll just be sending the unencrypted user’s data in the `authorization` header of each request.

Place the following code above the `app.get...;` line:

```

`const getTreatmentMiddleware = function (request: Request, response: Response, next: NextFunction) {
  const key: SplitIO.SplitKey = <SplitIO.SplitKey>request.headers['authorization'];
  request.treatment = client.getTreatment(key, 'timezone_split');
  next();
};`
<small id="shcb-language-18"><span>Code language:</span> <span>PHP</span> <span>(</span><span>php</span><span>)</span></small>
```

The sole purpose of the `getTreatmentMiddleware` is to put the treatment on the `request` object and proceed to the next middleware, which is the `getLocationsWithTimezones` function.

After adding this code, you’ll be getting an error from the TypeScript compiler – and a completely legit one – as there is no `treatment` property present on the `Request` interface, which is a type assigned to the `request` parameter. You shouldn’t think of this as a bad thing – TypeScript is doing here what the language was made for – warning the developer about the type errors in compile time to avoid (much more severe) errors for the end-user in the runtime. The compile error can be avoided by using a technique called _declaration merging_. That will effectively extend the `Request` interface provided by Express with your custom `treatment` property.

The way to expand Express declaration types is to create a declaration file inside the custom `@types` folder, with a structure that simulates the one located in `./node_modules/@types.` That means creating an `index.d.ts` file located at `./@types/express/index.d.ts` that will expand on Express type definitions found at `./node_modules/@types/express/index.d.ts`.

Create the `./@types/express/index.d.ts` file with:

```

`mkdir @types
cd @types
mkdir express
cd express
touch index.d.ts`
<small id="shcb-language-19"><span>Code language:</span> <span>Bash</span> <span>(</span><span>bash</span><span>)</span></small>
```

Your project tree should look similar to the structure on the image:

![Node TypeScript tutorial: viewing project tree](https://www.split.io/wp-content/uploads/2021/02/nodetypescript-08-project-tree-@types-express.png?width=544)

Populate the file with this code:

```

`export {}

declare global {
  namespace Express {
      interface Request {
          treatment?: any
      }
  }
}`
<small id="shcb-language-20"><span>Code language:</span> <span>C#</span> <span>(</span><span>cs</span><span>)</span></small>
```

Were you wondering about this wandering `export {}` statement from above? It is needed for this file to be understood as a _typescript module_, as only files with top-level `import` or `export` statements are interpreted as modules.

Add the `typeRoots` property to the `tsconfig.json` file, so the file now looks like this:

```

`{
  "compilerOptions": {
    "module": "commonjs",
    "target": "es6",
    "rootDir": "./",
    "esModuleInterop": true,
    "typeRoots": [
      "./@types",
      "./node_modules/@types"
    ] 
  }
}`
<small id="shcb-language-21"><span>Code language:</span> <span>JSON / JSON with Comments</span> <span>(</span><span>json</span><span>)</span></small>
```

This will ensure that the TypeScript compiler will search for types not only inside the `./node_modules/@types` folder, which is the default but also in the custom folder `./@types` that you’ve made. Finally, you can use the `treatment` property inside the `Request` interface in the `app.ts`, and the error in the console should disappear.

Let’s take a quick look on the angle bracket syntax (`<SplitIO.SplitKey>`) in this line of the middleware: `const key: SplitIO.SplitKey = <SplitIO.SplitKey>request.headers['authorization'];`. The angle brackets provide a nice TypeScript feature of _type casting_ a variable from one type to another. In this particular case, `request.headers['authorization']`, of type `string`, is casted into `SplitIO.SplitKey` type, as `getTreatment` function’s type definition expects the first argument to be of the `SplitIO.SplitKey` type.

Edit the routing line by adding a treatment middleware:

```

`app.get('/timezones', getTreatmentMiddleware, getLocationsWithTimezones);`
<small id="shcb-language-22"><span>Code language:</span> <span>C#</span> <span>(</span><span>cs</span><span>)</span></small>
```

Now it’s time to use the `request.treatment` value for branching inside the endpoint function.

## Route Branching with Feature Flags in Node

You should rework the `getLocationsWithTimezone` function to perform branching regarding the `request.treatment` value. Users who hit the `on` treatment will get an extra location in the response list – Kenya.

```

`const getLocationsWithTimezones = (request: Request, response: Response, next: NextFunction) => {
  let locations: LocationWithTimezone[] = [
    {
      location: 'Germany',
      timezoneName: 'Central European Time',
      timezoneAbbr: 'CET',
      utcOffset: 1
    },
    {
      location: 'China',
      timezoneName: 'China Standard Time',
      timezoneAbbr: 'CST',
      utcOffset: 8
    },
    {
      location: 'Argentina',
      timezoneName: 'Argentina Time',
      timezoneAbbr: 'ART',
      utcOffset: -3
    },
    {
      location: 'Japan',
      timezoneName: 'Japan Standard Time',
      timezoneAbbr: 'JST',
      utcOffset: 9
    }
  ];

  if (request.treatment == 'on')
    locations.push({
      location: 'Kenya',
      timezoneName: 'Eastern Africa Time',
      timezoneAbbr: 'EAT',
      utcOffset: 3
    });

  response.status(200).json(locations);
};`
<small id="shcb-language-23"><span>Code language:</span> <span>JavaScript</span> <span>(</span><span>javascript</span><span>)</span></small>
```

Things will soon get more clear after you check what the endpoint returns with a curl request that uses an `authorization` header:

```

`curl http://localhost:3000/timezones -H "authorization:user1"`
<small id="shcb-language-24"><span>Code language:</span> <span>Elixir</span> <span>(</span><span>elixir</span><span>)</span></small>
```

> The value of `user1` obviously doesn’t make much sense as the real authorization header. It’s used here just as an example to show how the feature flag key is used and what calculations are made based on that value.

Since we set the treatment up with a 50/50 split, you could get either response. So the Schrodinger’s response you are getting either includes or doesn’t include Kenya. The important thing is that every subsequent request with the same header value, or the same Split key, will give you the same treatment. Split ensures a [consistent user experience](https://help.split.io/hc/en-us/articles/360030024391-How-does-Split-ensure-a-consistent-user-experience-).

Calculations that Split performs behind the scenes guarantee that for the same key parameter (`user1`), the `getTreatment` method returns the same treatment value every time, or at least until you say so.

Now try something different; for example, increment the number in the header value:

```

`curl http://localhost:3000/timezones -H "authorization:user2"`
<small id="shcb-language-25"><span>Code language:</span> <span>Elixir</span> <span>(</span><span>elixir</span><span>)</span></small>
```

_Even a minor change in the Split key that gets sent with the `getTreatment` method results in a different set of treatment calculations provided by Split_. Again, this request has a 50% chance of resulting in either the `on` or the `off` treatment. If you are getting back the same response for `authorization:user2` as for the `authorization:user1`, you can keep incrementing the number in the header, and eventually, you’ll get a different treatment resulting in a different response.

## Reallocate the Feature Flag

Sometimes the consistent user experience provided by percentage split isn’t what you necessarily want all the time. As previously hinted, that can be stopped by the split author. In some situations, you’d like to change the treatment some users are getting without changing the targeting rules. This can be easily achieved by [split reallocation](https://help.split.io/hc/en-us/articles/360020528352-Reallocate). After this action, the configuration, including the targeting rules, will remain intact, but the treatment will be recalculated for each user.

To reallocate the split, click on the three-dot menu in the upper-right corner of the `timezone_split` inside the Split dashboard, and then click **Reallocate**.

![Node TypeScript tutorial: locating the Reallocate command in the drop-down menu of Split's UI.](https://www.split.io/wp-content/uploads/2021/02/nodetypescript-09-reallocate-dropdown.png?width=728)

In the dialog, just type `REALLOCATE` in the first input field and click **Reallocate** again.

![Node TypeScript tutorial: Typing "REALLOCATE" into the Reallocate split UI.](https://www.split.io/wp-content/uploads/2021/02/nodetypescript-10-reallocate-split-1024x815.png?width=1024)

Now restart your server and try the first request again via curl:

```

`curl http://localhost:3000/timezones -H "authorization:user1"`
<small id="shcb-language-26"><span>Code language:</span> <span>Elixir</span> <span>(</span><span>elixir</span><span>)</span></small>
```

The treatment for this request is calculated again, thanks to the split reallocation. There is a 50% chance that this request’s treatment will be different than the one before the allocation. If you are getting the same treatment again, try to reallocate the split and restart the server again. Eventually, you’ll get a different treatment.

## Feature Flags in Real World Node + TypeScript Apps

This is a vivid example of how feature flags can serve different responses based on specific targeting. In this case, the targeting was random and consistent at the same time. Imagine an A/B testing situation where you don’t know which solution is better, and you can’t target a specific slice of the users by any definable criteria, but you want them to have a consistent experience during the testing phase. That situation would require random but consistent targeting, as shown here.

If you want to see it all in one place, this is how `app.ts` file looks like in the end:

```

`import express, { Request, Response, NextFunction } from 'express';
import split = require('@splitsoftware/splitio');

interface LocationWithTimezone {
  location: string;
  timezoneName: string;
  timezoneAbbr: string;
  utcOffset: number;
};

const app = express();
const port = 3000;

app.listen(port, () => {
  console.log(`Timezones by location application is running on port ${port}.`);
});

const factory: SplitIO.ISDK = split.SplitFactory({
  core: {
    authorizationKey: YOUR_API_KEY
  }
});

const client: SplitIO.IClient = factory.client();

const getLocationsWithTimezones = (request: Request, response: Response, next: NextFunction) => {
  let locations: LocationWithTimezone[] = [
    {
      location: 'Germany',
      timezoneName: 'Central European Time',
      timezoneAbbr: 'CET',
      utcOffset: 1
    },
    {
      location: 'China',
      timezoneName: 'China Standard Time',
      timezoneAbbr: 'CST',
      utcOffset: 8
    },
    {
      location: 'Argentina',
      timezoneName: 'Argentina Time',
      timezoneAbbr: 'ART',
      utcOffset: -3
    },
    {
      location: 'Japan',
      timezoneName: 'Japan Standard Time',
      timezoneAbbr: 'JST',
      utcOffset: 9
    }
  ];

  if (request.treatment == 'on')
    locations.push({
      location: 'Kenya',
      timezoneName: 'Eastern Africa Time',
      timezoneAbbr: 'EAT',
      utcOffset: 3
    });

  response.status(200).json(locations);
};

const getTreatmentMiddleware = function (request: Request, response: Response, next: NextFunction) {
  const key: SplitIO.SplitKey = <SplitIO.SplitKey>request.headers['authorization'];
  request.treatment = client.getTreatment(key, 'timezone_split');
  next();
};

app.get('/timezones', getTreatmentMiddleware, getLocationsWithTimezones);`
<small id="shcb-language-27"><span>Code language:</span> <span>C#</span> <span>(</span><span>cs</span><span>)</span></small>
```

Using feature flags can bring your software product to a whole [new level](https://www.split.io/blog/continuous-deployment-feature-flags/). The Node TypeScript example shown here is just a small peek inside various ways feature flags can be used to give the best possible experience to your application’s end users.

## Learn More About Node, TypeScript, and Feature Flags

You’ve reached the end of the tutorial here, but feel free to continue learning about Node and TypeScript – a complementary set of tools for creating great server-side applications. Here are a few links to get you started:

- Bookmark [Split’s Node.js SDK Documentation](https://help.split.io/hc/en-us/articles/360020564931-Node-js-SDK)
- Build a library book API (another self-contained Node.js tutorial you can use or share): [Get Started with Feature Flags in Node](https://www.split.io/blog/node-js-feature-flags/)
- Spin up an [example application showcasing integration of the Split JavaScript SDK on a React + Redux codebase](https://github.com/splitio/react-redux-sdk-examples).