Tuesday, June 9, 2015

Talking TypeScript on the .NET Rocks! Podcast

I appeared on the .NET Rocks podcast show #1149 this week.  I had a blast talking about TypeScript, the new ES6 features coming in TypeScript 1.5, and grunt-ts, our TypeScript compiler task for Grunt.

I wanted to add a few things.

Firstly, here are a number of additional links that are relevant to our discussion:

My Pluralsight Course: Practical TypeScript Migration
Great review of what it's been like working with TypeScript over 24 months:  http://tedpatrick.com/2014/10/16/24-months-with-typescript/
Destructuring in ES6: https://hacks.mozilla.org/2015/05/es6-in-depth-destructuring/
Get started with grunt-ts if you've never used Grunt: https://github.com/TypeStrong/grunt-ts/blob/master/docs/DetailedGettingStartedInstructions.md
Node Inspector - debug Node.js code in the Chrome Dev Tools - works great with TypeScript also: https://github.com/node-inspector/node-inspector
Download TypeScript 1.5 beta for Visual Studio 2013 (transpiles much of ES6): https://visualstudiogallery.msdn.microsoft.com/107f89a0-a542-4264-b0a9-eb91037cf7af
Download TypeScript 1.4 for Visual Studio 2013 (current official release with minimal ES6 transpilation support): https://visualstudiogallery.msdn.microsoft.com/2d42d8dc-e085-45eb-a30b-3f7d50d55304

Around the 10 minute mark, I said that you should put type annotations on function calls.  That would be awful – I meant to say you should put type annotations on function declarations.

Around the 20 minute mark, I said that you can use ES6 features today with TypeScript 1.5 because it offers some transpilation features.  Richard then said transpilation was interesting because (paraphrasing) "when browsers come out with finished ES6 implementations, your page should go faster", and I sort of disagreed.  The reason is that transpiling actually changes your code from using one pattern to code using a different pattern.  Richard's statement was correct with regards to polyfills which is something that a dynamic language like JavaScript makes possible.  Developers who create polyfills attempt to implement future features in legacy environments.  For example, in ES6, there is a new `hypot` method on the JavaScript Math object, so Math.hypot(3,4) === 5.  A polyfill could be created for that feature to work in ES5 fairly easily.  A well-written polyfill would check to see if there was already a hypot property on the Math object; if so, it would just fall back to the native implementation which would (theoretically) be faster (though for something simple like a hypotenuse calculation it'd likely be no different).

Features that there's no way to polyfill require transpilation.  For example: class MyClass { }.  There is no (usable) class keyword in ES5, and so there is no way to create something in ES5 at runtime that would allow that code to run and do something reasonable; the syntax just doesn't exist.  That's why the transpilers have to change that code into a function declaration.  Since it becomes a function declaration, there's no way to natively optimize it as a class (beyond general optimizations for constructor function patterns that the engines would already have).  So for transpiled features, if you want to let the engine act natively, you'd have to dynamically serve the right code to the right engines - or (more practically) just serve the lowest common denominator like ES5 to all, which generally works great in today's browsers.

// Here's a cool destructuring example:
// This is valid TypeScript (in 1.5) and JavaScript (ES6)
// TypeScript will compile it down to work correctly with ES5
//  by creating a "normal" parameter in the signature of doSomething
//  and add code in the body to pull out its baz property.

var myObject = {
  foo: 1,
  bar: false,
  baz: "hello"

function doSomething({ baz }) {

doSomething(myObject); // hello

I said something silly around the 36 minute mark: "convert the inside of a tight loop first"; that's a very bad idea and doesn't even really make sense. :-(  What I should have said is "convert something central to your application first - like a common utilities library or a configuration file".  The reason for converting "from the inside out" as I recommend is that each new thing you convert will infer many types from the things that have already been typed.  As you grow the scope of TypeScript in your application, you will begin to find that you need to annotate less and less (other than function signatures) - and the things you do need to annotate may even be errors.  I feel that annotating function signatures is something that ultimately helps you write better code since it leads to compiler-enforced documentation, and it's usually necessary if you've activated --noImplicitAny.

Around the 51 minute mark, I was talking about how TypeScript doesn't help people enough with regards to componentizing projects of medium complexity and I misspoke a few times by using the word Solution (meaning a Visual Studio Solution) when I meant to say Project (meaning a Visual Studio Project).  TypeScript works great within a single Visual Studio project - the trouble comes when you want to use TypeScript across projects (like in a large/complex solution).  There are many hacky workarounds to this, but I still don't know of a great "this is the obviously right way to do it" story; I hope that the TypeScript team and the community will eventually put together a great solution for this.

I had a great time appearing on the podcast – thanks for the opportunity!


  1. I thought you were great on the show Steve.

    Kudos for picking up and detailing where you made the odd error but you really don't need to beat yourself up too much! We all make mistakes and 99% of what you had to offer was gold.