Setting up a TypeScript project

This year, I decided to learn TypeScript, or more precisely, to improve my very basic knowledge of the most popular flavor of JavaScript.

I know some basic TS and I use ExecuteProgram to improve my knowledge each day but I believe that nothing makes you learn faster than building stuff with your language (library, framework, etc.) of choice.

I haven't decided on a side-project yet so I'll start by doing some ad-hoc coding of stuff that comes to mind, add practicing every week.

What I'll surely need is to quickly set up projects with TypeScript and testing support and that's what I'll describe in this post.

Create a new project

I'll use pnpm which is a faster, less space-hungry version of npm. There are a myriad ways to install it, so just pick one if you also prefer pnpm.  

We start off by creating a new folder for the project:

mkdir portfolio-yield && cd portfolio-yield

As this is going to be a JS project (after all, TypeScript is just a flavor of JavaScript), let's create an empty package.json file first:

npm init # pnpm init

, and add the typescript package:

npm i -D typescript # pnpm add -D typescript

Next, let's create an empty tsconfig.json file where we can configure the TS compiler:

npm run tsc --init # pnpm tsc --init

The default options are fine for now, I'm sure I'll have to come back and tweak things later.

Running the compiler happens by running npm run tsc (or pnpm tsc), which compiles all the .ts files into .js in the project.  We can have a constantly running compiler process that watches for file updates and re-compiles changed source files by passing the -w (or --watch) option:

npm run tsc -w # pnpm tsc -w

Use vitest for testing

I decided to use vitest for testing because somebody asked on Twitter which testing library they should use and somebody answered vitest. Yes, that was my extent of my professional research.

Its DX also looks appealing and it's tagline says "blazing fast". As I expect to spend a lot of time running tests in these projects, that was a strong selling point. (Though, in reality, these side-projects will never get to be big enough for that to matter.)

npm i -D vitest # pnpm add -D vitest

Let's create a config file for vitest and place it in the root folder:

import { defineConfig } from 'vitest/config'

export default defineConfig({
  test: {
    // ...
  },
})
vitest.config.js

I'll now add a first test file in tests/growth.test.js that verifies that calculating the growth of a portfolio works correctly:

import { expect, test } from 'vitest';
import { growth } from '../src/index';

test('growth', () => {
  expect(growth(10, 15)).toBe(0.5);
  expect(growth(15, 10)).toBeCloseTo(-0.33, 2);
  expect(growth(10, 8)).toBe(-0.2);
  expect(growth(10, 10)).toBe(0);
})
tests/growth.test.js

(It seems that test files need to end with .test.js for vitest to pick them up.)

I like the expect kind of assertions that I last used with rspec, and you have to love toBeCloseTo!

Anyway, back to the hard world of non-aesthetics. The growth function is imported from the src/index module in the parent folder, so I'll create a filed called index.ts there and implement the function there:

export function growth(previousValue: number, currentValue: number) {
  return (currentValue - previousValue) / previousValue;
}

Running TS compilation and tests

We're now ready to run our first test. All we have to do to run the test is to type vitest. Not only will that run all tests, the process also keeps running and will re-run tests when we make any updates.

To be good node citizens, let's add a script to our package for each development process:

{
  "name": "portfolio-yield",
  "scripts": {
    "compile": "tsc -w",
    "test": "vitest"
  }
}

We can now simply run npm run compile (or pnpm compile)and npm run test (or pnpm test) to rebuild our source TS files every time they change and then run the tests again.

That'll do as our first milestone. Granted, TypeScript didn't give us anything yet but we've set up a TS project we can build on. Stay tuned for more!