Softwire Blog


Introduction to TypeScript: More Than Just Types


27 August 2015, by

In this post we’re going to take a look at the exciting extra features of TypeScript, and see what provides beyond just JavaScript with types.

This is the final post in our 4-part series on TypeScript, so do take a look at our previous posts on type inference, type annotations and type declarations for more background.

ES015 (aka ES6)

ES2015 has introduced a whole swathe of features, including arrow functions, classes, let/const and promises. Browser vendors are rapidly working to add these features, and so is TypeScript, in its ongoing effort to act as a superset of standard JavaScript syntax. Progress on this so far is good, with around 52% support for the new features added, compared to 48% for Chrome, 67% for Firefox and 66% for Edge. That 52% figure does require a browser that supports that ES6 syntax though (or a polyfill, like core-js), in addition to you compiling the TypeScript with the ‘--target ES6‘ option. Still, this means you can typically immediately start using ES6 features supported by your target browser set in TypeScript.

We can do better than this though. In lots of cases ES2015 features can be compiled back into ES5 or even ES3-compatible code, allowing you to use new ES2015 features right now, and run it even in substantially older browsers. This works to varying degrees, and is difficult to accurately measure since there’s a few specific cases that can’t be effectively worked around in special circumstances (like closuring a ‘let’ declaration within a loop), but overall TypeScript does currently support around 30% of the ES2015 features even when targeting ES5.

That means out of the box when writing TypeScript in an environment that doesn’t support ES2015, you can still immediately use:

  • Arrow functions:  (x) => x * 2
  • Destructuring:  var {a, b} = {a:1, b:2}
  • Spread operator:  function f(...x) { }; var xs = [1, 2, ...iterable, 5, 6];
  • For/of:  for (var x of [1, 2, 3]) { ... }
  • Let/const:  let x = 1; const y = "hi"
  • Template strings:  y = `hello ${myVar}`
  • Tagged template strings:  y = escapeHtml`<script>...</script>`
  • Classes (as seen in our previous post)
  • ES2015 modules (see ‘module systems’ below)
  • Unicode characters outside BMP:  "\u{1f4a9}"
  • Default parameters:  function f(a = 1) { }

And probably more, although there doesn’t seem to be an authoritative list anywhere. All of these get successfully compiled back into their non-ES2015 equivalents, allowing you to write enjoyably modern and clean ES2015 code without giving up on compatibility with older browsers. The TypeScript team are aiming to extend this further, wherever it’s possible to do so with reasonably simple and performant equivalents. All of the above fit that, and a few cases have no runtime impact at all: let/const are emitted just as ‘var’ statements for example, but checked for correct usage at compile time instead.

Paste any of above into the TypeScript Playground and take a look at the resulting compiled ES5 code that appears, if you want to see how this works in practice.

Extended class syntax

In addition to supporting the ES2015 class syntax, TypeScript also includes a few extensions. Some of these we’ve seen in previous posts, such as field visibility (public/private/protected), but there’s a couple of other interesting features.

Constructor parameter properties

class MyClass {
  constructor(private x: string) {}
}

In a syntax similar to that of Scala, TypeScript provides a shorthand to let you take a parameter in your constructor and immediately assign it to a public, private or protected field. The above code is exactly equivalent to (but shorter and simpler than):

class MyClass {
  private x: string;
  constructor(x: string) {
    this.x = x;
  }
}

Decorators

Taking a leaf from the current ES2016 (ES7) drafts, in turn heavily inspired by Python, TypeScript 1.5 includes support for class, method, property and parameter decorators. These are quite complicated and very new (feel free to read the ES7 proposed implementation docs for all the gory details), but provide some exciting new options for flexibility and DRY code when defining classes.

The usage of the 4 various decorator types looks like:

@myClassDecorator
class AClass {

  @myPropertyDecorator
  private x: string;
  
  @myMethodDecorator
  public f(@myParamDecorator x: number) { }  

}

In each case, the decorator wraps the decorated element, and potentially redefines or extends how it works.

You can for example create a @log method decorator that logs a message before and after the method is called, to give you a trace you can analyse to understand the flow in your application. Each form of decorator works in a slightly different way to allow this kind of wrapping; a class decorator is given the class’s constructor for example, and must return the new constructor that will replace it.

Digging into the depths of this is really out of the scope of this post, but decorators are a complicated and powerful tool for sharing cross-cutting logic between multiple classes that’s well worth learning to keep your code clean as your codebase expands. Take a look at this excellent TypeScript writeup if you’re keen to start looking into understanding and using these immediately (but I’d recommend getting to grips with the rest of TypeScript first).

Note again, as with many of the ES2015 features, that this is backward compatible and happily compiles down to standard ES5 code, so you can start writing code using it immediately.

Module systems

For a long time JavaScript has had an ongoing battle between various approaches to modularization, from globals to IIFE to CommonJS and AMD, to ES6 modules, and more, each introducing different syntax, functionality, and new sets of problems.

TypeScript lets you push straight past this. TypeScript includes it’s own standard built-in module system, sticking closely to the standard ES6 approach, and automatically hooked into the type system, so it can understand the type of the value that’s just been imported by looking at its corresponding source at compile time. The syntax for this is fairly simple and easy to understand if you’ve ever used either CommonJS or the new ES6 modules:

file1.ts:

export default function myFunction(): boolean {
  ...
  return true;
}

file2.ts:

import myFunction from "./file1";

var y: boolean = myFunction(); // understands types from the other file automatically

There’s more to it than this, but that’s the essence. The reason this is particularly intesting though, rather than just being another ES2015 feature, is that the output module format of TypeScript compilation is configurable. By specifying the ‘--module‘ argument, you can compile from this to code that supports any other module format supported. Currently that’s:

  • CommonJS
  • AMD
  • UMD
  • SystemJS
  • ES6 (by specifying ‘--target es6‘ and not specifying the ‘module’ argument)

This lets you write code in the most modern and powerful format available (ES2015 modules), while transparently compiling back to whatever format you need to use to integrate with the rest of your existing code and libraries.

Coming soon…

All this is already in TypeScript, but there’s more coming soon too! The full roadmap is available at github.com/Microsoft/TypeScript/wiki/Roadmap, and it’s worth being aware of some of the particular highlights:

  • Async/await – drawn from ES2016, inspired in turn by C#. Synchronous looking and feeling APIs for async code, to make asynchrony as frictionless as possible
  • Generators – another ES2015 feature, this one coming from Python. Syntax for describing functions that can repeatedly return values on demand, letting you treat them as iterables
  • JSX support – fluent syntax for creating HTML elements when using React

The End

This concludes our 4-part series on TypeScript. Hopefully it’s been an interesting insight into the language, how and why you might use it, and given you an itch to try it out! TypeScript is a exciting language, providing safety, structure, and a host of powerful features that can be used incrementally on top of the JavaScript you already writing, giving you remarkable flexibility to progressively pull modern development practices from a range of other languages into your JS.

If you are interested in having a closer look, the easiest way to quickly a go yourself is with the TypeScript playground. Setting it up in a real project isn’t much more complicated: you can build your code directly with the official command-line tool, or there’s plugins for grunt, gulp, broccoli, maven, gradle and probably whatever the latest flavour of the month build tool is. There’s also integrations abound in the tools you use for development, including Intellij, Visual Studio, Atom and Sublime Text.

Play around, try it out on your next project, and let us know your thoughts either at @SoftwireUK, or in the comments below.

Mentoring the start-up talent of the future, at #Festival of Code 2015


21 August 2015, by

What is Young Rewired State and the Festival of Code?

FestivalOfCode2015YRS is a worldwide community of digital makers aged 18 and under. YRS started running the Festival of Code seven years ago, and it has grown hugely since then. It is free for all young people.

The Festival runs for a week early in the summer holidays. Young digital pioneers, working with the support of volunteer mentors, collaborate to build apps, websites, games and problem solving algorithms aimed to help improve their communities. The only rule is that their projects have to use at least one piece of Open Data – anything from Twitter feeds and weather data, to research data from CERN, so long as it’s free and publicly accessible.

At the end of the week, the coders converge to showcase their projects and compete in the finals. This year, they presented their projects to expert judges, mentors and the press at the Birmingham International Convention Centre on 1st and 2nd August.

What do the youngsters and mentors get out of it?

Who better to hear from than a youngster who got involved?! See what George says.

The mentors also have a great time! As Will said, ‘Everyone worked really hard and had a great time; people’s enthusiasm reminded me of why I learnt to program’.

What did the coders at the Bristol centre build?

  • A spoiler alert browser extension hiding content from TV shows from web pages across the internet.
  • A Top Trumps-like game about local places.
  • A weather and accident map visualisation to explore the correlation between the two.
  • A game where you bet points on whether search terms become more or less popular on google.
  • A map of airports and their associated live data.

Who won the nationwide competition?!

Here’s TechCrunch Mike Butcher’s post on this year’s Festival, with a run down of the winners.

Some noteworthy facts:

  • In seven festivals, the numbers of girls involved has grown from 2% to 30%. You can see more about this in Emma Mulqueeny’s post – she founded the Festival of Code.
  • This year, there were 66 regional centres in the UK with over 1200 coders participating at the weekend showcase.

A huge thank you to our Bristol intern Will Price and developer Jake McKenna for giving up their week to support the participants.

Introduction to TypeScript: Type Declarations


19 August 2015, by

This is the 3rd post in our series on TypeScript. Take a look at the first and second in this series for an introduction to the basic of TypeScript, type inference, and type annotations. In this post we’re going to take a more detailed look at how we can define our own types in TypeScript, to be used by the inference engine and in our own annotations.

Defining your own types

Up until now we’ve looked at ways to describe types in terms of the predefined types available (e.g. string, number or HTMLElement). This is powerful alone, but defining our own types on top of this dramatically increases its usefulness. In TypeScript there are a few main ways to define a new type:

    • Type aliases: type ElementGenerator = (a: string, b: string, c: boolean) => HTMLElement

      The easiest option is to just define a new simpler name for an existing type. Type aliases (added in 1.4) let you do this. This new type can then be used exactly as you would any other type, but with a shorter easier snappier name.

      Note that this is mostly just adding readability to your code: unlike equivalents in other languages (such as Haskell’s newtype) structural typing means this doesn’t increase type safety. Since types are still matched only structurally you can’t define type minutes = number, and use that to check that your variable is set only with values that are explicitly specified as being of the minutes type; any number is always a valid minute.

    • Interfaces
      interface MyInterface {
        property1: number;
        anotherProperty: boolean[];
        aMethod(HTMLElement): boolean;
        eventListener: (e: Event) => void;  
      }
      
      // Interfaces can be extended, as in most other modern OO languages
      interface My2ndInterface extends MyInterface {
        yetAnotherProperty: HTMLElement;
      }
      
      // Similarly, interfaces can be generic as in other languages
      interface MyGenericInterface<T> {
        getValue(): T;
      }
      
      interface FunctionInterface {
        // Objects fulfilling this are callable functions, taking a number and returning a boolean
        (x: number): boolean;
      
        // We can also have hybrid interfaces: functions that also have properties (like jQuery's $)
        myProperty: string;
      }
      
      interface DictionaryInterface {
        // Objects fulfilling this act as dictionaries, with arbitrary string keys and numeric values
        [key: string]: number;   
      }
      

      Interfaces act mostly as you’d expect from languages like Java, C# and Swift, with a few extra features. Any function or variable that is annotated or inferred to have the type of the interface will only accept values that match this, giving you guarantees that your values are always what you expect. Note too that all of this is just for compile-time checking; this is all thrown away by the compiler after compilation, and your interfaces don’t existing in the resulting compiled JS.

      The key major difference between how this works and most other languages is that this type checking is done purely structurally. A value matches an interface only because they have the same shape, not because they’re explicitly indicated as being a member of that that interface anywhere else.

    • Classes
      class MyClass extends MySuperclass implements AnInterface {
        // Fields and methods can have private/public modifiers (they're otherwise public by default)
        private myField: number;
      
        constructor(input: number) {
          super("hi"); // Subclasses have to call superclasses constructors before initializing themselves
          this.myField = input * 2;
        }
      
        calculateAnImportantValue(newInput: number): number {
          return this.myField * newInput + 1;
        }
      
        // Classes can include property accessors
        get propertyAccessor(): number {
          return this.myField;
        }
      
        static myStaticFunction(xs: number[]): MyClass[] {
          return xs.map(function (x) {
            return new MyClass(x);
          });
        }
      }
      
      // Classes are instantiated exactly as in vanilla JavaScript.
      // (The type alias here is just for clarity; it'd be inferred anyway)
      
      var instance: MyClass = new MyClass(10);
      

      Classes simultaneously define two things: a new type (the corresponding interface for the class), and an implementation of that type. The actual implementation of this acts the same as the new built-in class functionality in ES2015 (ES6) – defining a constructor function and attaching methods to the prototypes – but

      You are only allowed one implementation per function in Typescript (including the methods and constructor here) to ensure compatibility when using the compiled code from pure JavaScript, so there’s no method overloading like you might’ve seen elsewhere. You can have multiple type definitions for a function though to simulate this yourself, although it’s a bit fiddly. Take a look at function overloads in the TypeScript handbook for the gory details.

    • Enums
      enum Color {
        Red,
        Green,
        Blue
      }
      
      var c: Color = Color.Blue;
      

      Another nice feature, straight from the standard OO playbook. Enums let you define a fixed set of values with usable friendly names (underneath they’re each just numbers, and an object to let you look up numbers/names from one another).

      Structural typing here is actually something of a hinderance however, limiting the value of enums compared to elsewhere. Enums become far more powerful within nominal type systems, whereas in TypeScript you sadly can’t check a method that takes a Color from above isn’t given any old potentially invalid number instead, for example. Take a look at the TypeScript playground at http://goo.gl/FZMzaj for a happily compiling but totally incorrect example.

      Nonetheless, while enum’s safety-giving power is limited they can still bring quite a bit of clarity and simplicity to code, and are definitely a useful tool regardless.

Describing external types

Sometimes you want to use TypeScript code that you didn’t write, but you’d still like it to be safely typed. Fortunately TypeScript supports exactly that.

Using the above type definitions we can describe the full shape of an external library totally externally to it, without having to actually change the code. Structural typing means the original library code doesn’t need to specify which interfaces it supports, and we just need a definition of the interface of the library, and to tell TypeScript that a variable matching this interface is available.

To do that, we use ambient modules; these describe modules of code that are defined outside our codebase. They can be either ‘internal’ (the variables declared are already defined in the global scope, typically by a script tag somewhere) or ‘external’ (the variables declared are exposed by a library that needs to be loaded through a module loader like CommonJS or AMD – we’ll look at TypeScript modules in a later post).

This is all very interesting, but helpfully you don’t really need to go any deeper than that for now. The syntax for this isn’t particularly important for TypeScript development day-to-day (although the section in the TypeScript handbook includes a few illustrative examples), because it’s already been done for you, for almost library you’ll use, as part of a project called DefinitelyTyped.

DefinitelyTyped includes not only type definitions for every library you might want (e.g. jQuery, lodash or loglevel), but also its own package manager TSD, to automatically retrieve and updates these type definitions for you.

To get started with this, just install TSD (npm install tsd -g), install the type definitions you need (tsd install jquery knockout moment --save), and ensure they’re referenced in your compilation process (e.g. include them as files to compile on the command line to tsc, add them to your input files list in grunt-ts, or use <reference> tags). TypeScript will know the variables exposed by each library and their types, giving you strong static typing wherever they’re used.

Bonus TypeScript Features

With this 3rd post, you’ve now seen the core of everything TypeScript has to offer, when automatically inferring types, manually annotating types yourself, and defining your own types to extend inference and annotation even further.

That’s not all TypeScript has to offer though. On top of this, TypeScript adds a selection of interesting bonus features, drawn from both ES2015 (ES6) and other languages, but compiling down into backward-compatible JavaScript you can run anywhere. Watch this space for the 4th and final post in this series, where we’ll take a closer look at exactly what’s available there, and how you can put it to use.

Announcing Softwire’s Technical Training Courses


14 August 2015, by

At Softwire we’re hugely committed to helping our employees build their skills – we can clearly see the value delivered by our investment in training paying off in team and individual performance. As we’ve grown as a company, this type of internal training activity has become an increasingly important and valued activity, and many of our more experienced staff have discovered a real passion for sharing their knowledge and experience.

We’re therefore tremendously excited to announce that starting later this year we’ll be opening up our technical training to a wider audience and offering it as another service to site alongside our existing software development and consultancy options. We think Softwire training offers a powerful combination of both a depth of real-world experience, built up over 15 years delivering high quality software projects, and a fresh and up-to-date perspective driven by our focus on staying abreast of the best emerging technologies.

We’ve created a schedule of courses this Autumn covering a wide range of different areas including:

Developer-focused courses

Technical leader courses

Business-focused courses

As a result we very much hope there’s something for everyone there. On top of that we’ve also partnered with the brilliant Seb Rose and Liz Keogh who have both hugely impressed us at conferences in the past to join us and deliver their own insightful perspectives with courses on “Agile Software Architecture” and “Behaviour Driven Development with Cynefin” respectively.

You can view full details of our courses on the links above. We’ll also be talking about a few of them in more detail in future blog posts.

Introduction to TypeScript: Type Annotations


14 August 2015, by

This is the 2nd post in our series on TypeScript. Take a look at the first post in this series for a bit more of an introduction to the basic of TypeScript, and the powers of type inference. In this post we’re going to take a more detailed look at the type annotations TypeScript provides to explicitly describe types, extending the power of static typing over more of our code that type inference can’t quite cover.

Extending types beyond pure inference

The simplest approach to typing your TypeScript code is to let type inference do it for you. This works well for locally defined and used variables, but falls down in cases where TypeScript can’t see enough context to know exactly what values we’re expecting. TypeScript infers types for variables by the values they’re initialised to, and by seeing them either returned by or provided as arguments to functions for which it already has types. That doesn’t cover many cases though, particularly the types of arguments in new function definitions, types for variables that aren’t immediately initialised, and any use of variables outside of the compiled TypeScript code (e.g. code coming from external JavaScript libraries).

This doesn’t necessarily result in a failure to compile your code. Variables that don’t have inferable types are given the ‘any’ type: a dynamic type that opts them out of type checking, and blindly trusts their usage. You can disable this by enabling the noImplicitAny) flag to require strict typing everywhere, but this is often useful behaviour initially; treating unknown variables as any allows you to gradually type a codebase, rather than forcing you to ensure everything is fully typed immediately. It’s rarely what you want in the long-term though. Types catch bugs, and the more specific you can be about the types you’re expecting, the more mistakes you’re going to catch at compile-time, before they hurt.

In these cases then where TypeScript can’t infer our types, how to we specify them? First the basics:

var x: string;

function aFunctionWithTypedArguments(a: number, b: Array<number>): void { ... }

function aFunctionReturningAnElement(): HTMLElement { ... }

function aGenericFunction<T>(arg: T): Array<T> { ... }

Here we annotate types on a variable, function arguments, function return types, and a generic function’s argument and return types. With these in place the compiler can now validate these types are correct (refusing to any attempts to call the 1st function with two numbers, for example), and can use these types in future inferences (for example automatically inferring the type of ‘c’ in var c = aFunctionReturningAnElement();).

Hopefully this is fairly intuitive to anybody who’s written code in a statically typed language before; all of this acts just as you’d expect coming from languages like Java or C#.

Note the generic code particularly. While this might look complex to anybody only familiar with JavaScript, it’s fundamentally the same as the generics used in throughout many popular statically typed languages. aGenericFunction here is a function that takes an argument of any type, and returns an array of that type: e.g. aGenericFunction(1) is guaranteed to return an array of numbers.

More complex type annotations

That’s it for the simple case. Unfortunately JavaScript has quite a few more complicated types than this though, and TypeScript aims to let you to describe all of the types that we see in real world JS. To do this TypeScript provides some more unusual types to effectively describe more complex structure:

  • Inline function types: var callback: (e: Event) => boolean

    JavaScript APIs tend to be very fond of passing functions around, particularly for callbacks, and the type system has to be able to keep up. The signatures for this is simple: brackets listing the argument types, and an arrow (=>) to the return type.

  • Anonymous object types: var x: { name: string };

    TypeScript has a structural type system: a variable matches a type if it has the same structure. X is matches type T if X has all the properties that T has, with the same types. You can think of this as compile-time duck typing. This differs drastically from languages like C# or Java with nominal type systems, where types match only if there’s an explicit relationship between them (e.g. one one is a subclass of the other, or explicitly implements its interface).The end result is that you can define types by their structure alone. Above for example is a variable that can be assigned any object with a name property that’s a string. TypeScript will then allow you to set it to any kind of object from any source, as long as it fulfills that description, and catch any cases that don’t fit that at compile time. This is a key, as lots of existing JavaScript depends on duck-typing, and would be extremely difficult to externally type with a more traditional OO type system.

  • Union types: var x: string|number

    Union types are a fairly new TypeScript feature, added in 1.4. They allow you to describe a variable as either being of type A or type B, and will only allow you to perform operations valid on both. To then pick a specific one of the two options you can use type guards: if (x instanceof string) { ... }. TypeScript’s inference engine understands type guard expressions like these, and will allow you to use the variable as the specific type that you’ve checked for within the body of the if block.In addition TypeScript also has explicit casting, like many statically typed languages, for cases where you want to tell the compiler you’re already sure what type something is (var y = <number> x;).Like structural typing, union types are useful because they closely match common patterns used in existing JavaScript code. Many libraries (e.g. JQuery) return completely different types of variable depending on the specific arguments provided at runtime, and this provides a very effective way of explicitly describing and handling that case.

Defining your own types

That’s the essence of how you annotate your types in TypeScript. With this, you can add annotations describing the core structure and contracts with your code, to get type checking across your codebase.

This is still a bit limited though: we can only use built in types (number, string, HTMLElement), or combinations and structures we build from those explicitly. In the next post in this series we’ll take a closer look at that, and the tools TypeScript provides to let you define your own types, with classes, enums, and more.

Introduction to TypeScript: Type Inference In Practice


3 August 2015, by

TypeScript is a powerful compile-to-JS language for the browser and node, designed to act as a superset of JavaScript, with optional static type annotations. We touched on it years ago when it was first released, but version 1.5 is coming soon, and it’s time for a closer look!

In this post, I want to first take a look at what type inference TypeScript gives you on vanilla JS, and why you that might be something to care about, before we later start digging into the extra constructs TypeScript provides.

What is TypeScript?

TypeScript as a language is very similar to JavaScript, but bringing in type inference, access to future features (due to the compile step), support for more structure, and optional type annotations, all while remaining a strict superset of JavaScript.

Type inference and annotation are the killer features here: it allows you to annotate variables with these type annotations as you see fit, and then uses an extremely powerful type inference engine to automatically infer types for much of the rest of your code from there, automatically catching whole classes of bugs for you immediately. This is totally optional though, and any variables without types are implicitly assigned the ‘any’ type, opting them out of type checks entirely, allowing you to progressively add types to your codebase only where they’re useful, according to your preferences.

Catching bugs for free (almost) with static type inference

Below is a very simple example chunk of vanilla standalone JavaScript. There are a selection of showstopping bugs in the below; without reading on, how many can you spot?

 

navigator.geolocation.getCurrentPosition(function onSuccess(position) {
  var lat = position.latitude;
  var long = position.longitude;

  var lastUpdated = Date.parse(position.timestamp);
  var now = new Date();
  var positionIsCurrent = now.getYear() === lastUpdated.getYear();
	
  if (positionIsCurrent) {
    var div = document.createElement("div");
    div.class = "message";
    div.style = "width: 100%; height: 100px; background-color: red;";		
    div.text = "Up to date position: " + lat + ", " + long;
    document.body.append(div);
  } else {
    var messageDivs = document.querySelectorAll("div.message");
    messageDivs.forEach(function (message) {
      message.style.display = false;
    });
  }
}, { enableHighAccuracy: "never" });

 

Done?

In total there’s actually 12 bugs in here, ranging from the easily spottable (it’s .appendNode() not append(), which will crash with an undefined method exception as soon as you start testing), to the more subtle (enableHighAccuracy is a boolean and “never” is truthy, so this unintentionally turns on your GPS and waits until the position is accurate enough, and various assignments to incorrect properties will just silently do nothing). All 12 of these are caught by TypeScript automatically however, when run on this vanilla JavaScript source just with type inference, no type annotations.

Take a look at a commented version for some more details, with these issues automatically caught by the TypeScript compiler, in the TypeScript playground at http://goo.gl/L9qp8o.

This then gets even more powerful once you do start annotating parameters, to provide more information in the cases it can’t automatically spot for you. Of these, how much time would it take to trace these bugs down? How does a compiler that points out each of these half a second after you add it sound?

Types are powerful. They don’t catch all bugs by any means, and good test coverage remains important, but type checking is an easy and effective method to totally immediately remove an entire class of bugs from your codebase, to let your testing instead focus on actual functionality and behaviour, rather than just checking your code is sensical.

A key point here is the speed of feedback: writing + running your tests is always going to be a slower and far more time consuming process than compiling your code, and good IDEs (both Visual Studio and Intellij) will give you line by line feedback in sub-second times when you write code that won’t compile. This is something that great tools like JSHint can provide, but while they’re definitely useful, without understanding the types in a codebase they’re severely hampered. In the above code, JSHint sees no issues whatsoever.

TypeScript meanwhile catches these issues, working with your vanilla JS code out of this box, for near-zero effort (near-zero: there’s a small bit of setup required to add the compile step, but very very small, and it shouldn’t require any code changes). This is no panacea, there’ll still be bugs and you’ll still need to test your code heavily, but with types you’ll at least already have the confidence that there’s nothing totally drastically wrong before you do so.

Going beyond this

That’s enough for one post, but hopefully starts to give you a taste of what TypeScript can provide above and beyond JavaScript.

This post is the start of a series on TypeScript; in the next post we’ll take a look at type annotations, and how you can extend this power to cover all your code, not just code where the types are easily inferrable, to take this even further. If you’re hungry for more in the meantime, take a look at TypeScriptLang.org for the full guide into the details of how TypeScript works, or ping us on Twitter with your questions and thoughts.