Lately, I have been hearing a lot about TypeScript. I besides developing applications in ES6, thought why not try TypeScript and check what is all the fuss about . Moreover, there were a couple of requests on our open-source project ReactPWA for adding support of TypeScript. So with this purpose in mind I thought of sharing my finding with everyone while I learn TypeScript in form of a blog series.

End goal

  • Firstly, I want to learn TypeScript with correct methodology and understand it in depth rather than follow random tutorials
  • Secondly, create the all famous “Hello, World!” setup with TypeScript, WebPack and ReactJS
  • Thirdly, handle TypeScript definitions (At this point I have just heard about it and have no clue what they are or how they function)
  • Finally, testing

Let’s hope it turns out pretty simple!

What is TypeScript?

Wikipedia briefs me:

TypeScript is an open-source programming language developed and maintained by Microsoft. It is a strict syntactical  superset  of JavaScript and adds optional static typing to the language.
TypeScript is designed for development of large applications and transcompiles to JavaScript. As TypeScript is a superset of JavaScript, existing JavaScript programs are also valid TypeScript programs. TypeScript may be used to develop JavaScript applications for both client-side and server-side (Node.js) execution

https://en.wikipedia.org/wiki/TypeScript

Even though, this is a good piece of information, but I lost a bit of confidence hearing it as it was developed and maintained by Microsoft, but let us not judge it yet.

By googling more I understood the following:

ES6 enhances ES5 and we use babel transpiler to compile code from ES6 to ES5 until it is globally supported. TypeScript enhances the functionality of ES6, so basically it is a more strict version of ES6 with type checking (Type-Script). I love strict programming languages, it (tries to) prevents big enterprise collaborated project developers from making mistakes, thus improving the code quality. JavaScript has always missed type checking and thus it makes JavaScript a low ranked programming language compared to Java or C++ or any other typed language.

Well, which programming language is good and which has not always been a topic of discussion and opinion, But I personally love JavaScript and PHP both are not currently type checked.

I am really looking forward to getting my hands dirty with TypeScript and see if it helps me improve my writing better code.

Setting up a simple nodejs project

NOTE: I never ever add anything globally with nodejs npm i -g, it is just an obsessive-compulsive disorder that I have, so I have ignored many tutorials that ask me to add typescript globally.

I use the sublime text editor with typescript package installed in Ubuntu 18.10 operating system

I prefer to work in a separate work space to make sure not to mess up with another project (often most of us do the same). So I start by creating a folder in my workspace.

I shall also create a git repo to keep track of progress

mkdir -p ~/workspace/typescript-series && cd ~/workspace/typescript-series
npm init

I have added the information below for my npm project, modify yours as per your details:

{
  "name": "typescript-series",
  "version": "1.0.0",
  "description": "an example series to get started with TypeScript",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/Atyantik/typescript-series.git"
  },
  "keywords": [
    "typescript",
    "react",
    "webpack"
  ],
  "author": "Tirth Bodawala",
  "license": "MIT",
  "bugs": {
    "url": "https://github.com/Atyantik/typescript-series/issues"
  },
  "homepage": "https://github.com/Atyantik/typescript-series#readme"
}

Please note that there are no commands added for testing right now. Will add them later on.

Adding typescript to the project

npm i typescript && touch index.ts

Ok. I think that should give me access to tsc & tsserver in node_modules/.bin thus adding the following to my package.json would help me execute with tsc (typescript compiler).

"scripts": {
  "start": "tsc index.ts && node index.js",
  "test": "echo \"Error: no test specified\" && exit 1"
},

The above start command simply compiles the index.ts file to index.js and then we execute index.js with node

Simple enough right?

Let me update the content of index.ts to a simple “Hello, World”

console.log("Hello, World!");

Running,npm start It compiled successfully and a file index.js was created with exactly the same content. thus it console logged “Hello, World!” as expected.
No magic yet. So let us assign a type to string “Hello, World!”, hence updating the index.ts to the following:

let str: string = "Hello, World!";
console.log(str);

So it is more like ES6 but you assign a type to the variable after a colon “:” like

let <variable-name>: <type-of-variable> = <default-value>;

Running, npm start worked and it created an index.js with the following content:

var str = "Hello, World!";
console.log(str);

No magic above! but if you change the value of the variable str to something other than string we get the following errors and sublime also warns about the invalid type assigned to the variable!

index.ts:2:1 - error TS2322: Type 'Date' is not assignable to type 'string'.

2 str = new Date();
  ~~~

The code refuses to compile! This is very cool. I am already loving it. But there is something not right here, It has still created an index.js with the following content:

var str = "Hello, World!";
str = new Date();
console.log(str);

Odd right? Well, I was not the only one who thought it was odd so I came across this issue
https://github.com/Microsoft/TypeScript/issues/828

So solution to the above problem is pretty simple, set noEmitOnError to true in compiler options!

Setting compiler options in TypeScript

So these are the two ways of doing it:

  • Update my package.json’s start command to tsc --noEmitOnError index.ts && node index.js
  • Create a tsconfig.json file to set compiler options.

I tested updating the start command and the index.js was not created as expected, after changing start command and creating a tsconfig.json I noted it would be more readable and extendable.

For that reason I created tsconfig.json in the root folder as shown below:

{
  "compilerOptions": {
    "noEmitOnError": true
  }
}

I expected it to work, but it didn’t! I looked more deeply into tsconfig.json
https://www.typescriptlang.org/docs/handbook/tsconfig-json.html where the following result was shown:

{
  "compilerOptions": {
    // ...compiler options
  },
  "files": [
    // ... list of files that should be affected by the compiler options, relative or absolute path
  ],
  "include": [
    // Glob pattern to include files
  ]
}

After trying the above code it also didn’t work, and thus came across the issue:
https://github.com/Microsoft/TypeScript/issues/6591#issuecomment-174343747
Which say:

The problem is that tsconfig.json isn’t considered when you manually specify your source files on the command line. It’s certainly not great behaviour, but I think it’s by design since if you use the --projectoption, you’ll get the following error:

DanielRosenwasser – A member

Updating the directory structure

Later on changing the CLI start script to tsc && node index.js should solve the issue, i.e. we are not specifying any input files and asking tsc to compile all the <name>.ts files in the current working directory to compile to <name>.js and yes it worked! But it is not a good solution, so lets change the directory structure as follows:

- Project Root
 -- node_modules
 -- src
   - index.ts
 - tsconfig.json
 - package.json
 - package-lock.json
 - LICENSE
 - .gitignore

After adding src folder and moving index.ts inside it. Thereafter, updating the tsconfig.json to the following:

{
  "compilerOptions": {
    "noEmitOnError": true,
    "outDir": "build"
  },
  "include": [
    "src/**/*"
  ]
}

After specifing the outDir in compilerOptions as I didn’t want the output compiled file in src folder, we ask ts compiler to look for everything in src folder and change the index.ts to an error free file removing the line:
<del>str = new Date();</del>
I also had to update the scripts section in package.json as below:
"start": "tsc &amp;&amp; node build/index.js",
Because we want to use tsconfig.json and the output will be in build folder.

Running npm start works as expected and outputs “Hello, World!” but I was not sure if I had a folder inside the src folder would the compiler maintain the directory structure so I just created src/component/test.ts that had a simple console.log("Testing sub-dir compile") and yes tsc did maintained the directory structure in the build folder so I had the following as my output:

- Project Root
 -- node_modules
 -- build
   -- component
     - test.js
   - index.js
 -- src
   -- component
     - test.ts
   - index.ts
 - tsconfig.json
 - package.json
 - package-lock.json
 - LICENSE
 - .gitignore

Which is what I would expect!

Well, that is all for today. I would continue more tomorrow in getting to know TypeScript better. Leave your comments if you would like me to continue this series.

UPDATE: Part 2 – ExpressJS server setup with TypeScript is now available:
https://www.atyantik.com/expressjs-server-with-typescript-part-2-the-novice-programmer/

Also, the code base of Part 1 is available at:
https://github.com/Atyantik/typescript-series/tree/part-1