Announcing TypeScript 2.1

We spread ourselves thin, but this is the moment you’ve been awaiting – TypeScript 2.1 is here!

For those who are unfamiliar, TypeScript is a language that brings you all the new features of JavaScript, along with optional static types. This gives you an editing experience that can’t be beat, along with stronger checks against typos and bugs in your code.

This release comes with features that we think will drastically reduce the friction of starting new projects, make the type-checker much more powerful, and give you the tools to write much more expressive code.

To start using TypeScript you can use NuGet, or install it through npm:

Visual Studio Code will usually just prompt you if your TypeScript install is more up-to-date, but you can also follow instructions to use TypeScript 2.1 now with Visual Studio Code or our Sublime Text Plugin.

We’ve written previously about some great new things 2.1 has in store, including downlevel async/await and significantly improved inference, in our announcement for TypeScript 2.1 RC, but here’s a bit more about what’s new in 2.1.

Async Functions

It bears repeating: downlevel async functions have arrived! That means that you can use async/await and target ES3/ES5 without using any other tools.

Bringing downlevel async/await to TypeScript involved rewriting our emit pipeline to use tree transforms. Keeping parity meant not just that existing emit didn’t change, but that TypeScript’s emit speed was on par as well. We’re pleased to say that after several months of testing, neither have been impacted, and that TypeScript users should continue to enjoy a stable speedy experience.

Object Rest & Spread

We’ve been excited to deliver object rest & spread since its original proposal, and today it’s here in TypeScript 2.1. Object rest & spread is a new proposal for ES2017 that makes it much easier to partially copy, merge, and pick apart objects. The feature is already used quite a bit when using libraries like Redux.

With object spreads, making a shallow copy of an object has never been easier:

let copy = { ...original };

Similarly, we can merge several different objects so that in the following example, merged will have properties from foo, bar, and baz.

Keep in mind that when using object spread operators, any properties in later spreads “win out” over previously created properties. So in our last example, if bar had a property named world, then bar.world would have been used instead of the one we explicitly wrote out.

Object rests are the dual of object spreads, in that they can extract any extra properties that don’t get picked up when destructuring an element:

let { a, b, c, ...defghijklmnopqrstuvwxyz } =alphabet;

keyof and Lookup Types

Many libraries take advantage of the fact that objects are (for the most part) just a map of strings to values. Given what TypeScript knows about each value’s properties, there’s a set of known strings (or keys) that you can use for lookups.

Notice all this repetition – ideally, much of the same information in each variant of Person could have been shared.

Let’s take a look at how we could write BooleanifiedPerson with a mapped type.

typeBooleanifiedPerson= {
[Pin"name"|"age"|"location"]:boolean
};

Mapped types are produced by taking a union of literal types, and computing a set of properties for a new object type. They’re like list comprehensions in Python, but instead of producing new elements in a list, they produce new properties in a type.

In the above example, TypeScript uses each literal type in "name" | "age" | "location", and produces a property of that name (i.e. properties named name, age, and location). P gets bound to each of those literal types (even though it’s not used in this example), and gives the property the type boolean.

Right now, this new form doesn’t look ideal, but we can use the keyof operator to cut down on the typing:

With mapped types, we no longer have to create new partial or readonly variants of existing types either.

// Keep types the same, but make every property optional.typePartial<T> = {
[PinkeyofT]?:T[P];
};
// Keep types the same, but make each property to be read-only.typeReadonly<T> = {
readonly [PinkeyofT]:T[P];
};

Notice how we leveraged TypeScript 2.1’s new indexed access types here by writing out T[P].

So instead of defining a completely new type like PartialPerson, we can just write Partial<Person>. Likewise, instead of repeating ourselves with FrozenPerson, we can just write Readonly<Person>!

Partial, Readonly, Record, and Pick

Originally, we planned to ship a type operator in TypeScript 2.1 named partial which could create an all-optional version of an existing type.
This was useful for performing partial updates to values, like when using React‘s setState method to update component state. Now that TypeScript has mapped types, no special support has to be built into the language for partial.

Easier Imports

TypeScript has traditionally been a bit finnicky about exactly how you can import something. This was to avoid typos and prevent users from using packages incorrectly.

However, a lot of the time, you might just want to write a quick script and get TypeScript’s editing experience. Unfortunately, it’s pretty common that as soon as you import something you’ll get an error.

“But I already have that package installed!” you might say.

The problem is that TypeScript didn’t trust the import since it couldn’t find any declaration files for lodash. The fix is pretty simple:

npm install --save @types/lodash

But this was a consistent point of friction for developers. And while you can still compile & run your code in spite of those errors, those red squiggles can be distracting while you edit.

So we focused on on that one core expectation:

But I already have that package installed!

and from that statement, the solution became obvious. We decided that TypeScript needs to be more trusting, and in TypeScript 2.1, so long as you have a package installed, you can use it.

Do be careful though – TypeScript will assume the package has the type any, meaning you can do anything with it. If that’s not desirable, you can opt in to the old behavior with --noImplicitAny, which we actually recommend for all new TypeScript projects.

> Does it not use the javascript type annotations of the library (if available)

If one is available it will be used, no error will be reported. the error is reported if a `.js` file was found with no `.d.ts` to use. it will be considered `any`, and an error will be reported for it if you have `–noImplicitAny` on.

I was wondering about this section: Partial, Readonly, Record, and Pick.

To me it’s pretty clear what partial, readonly and pick (just grab a few of the properties) do. But could you provide a small example (either in the post or just here in the comments) for what “Record” does?

I’m guessing it’s related to the “booleanify” example you had before, but a small explanation would really help.

I don’t get one thing: downlevel async-await seems to generate state machine that goes through generator (it’s even called __generator). Why in that case async-await is transpiled down-level but generator functions are not, if they could use just the same helper? (this is similar to what facebook/regenerator does)

Nice release!
I have a concern regarding the “easier import”:
Babel generates code to import ‘*’ when the imported module has no default exports. For instance this is working with babel:
`import React from ‘react’;`
With TS, the same code will result in `React` being undefined 🙁
This difference makes converting Babel projects to TS pretty painful.
I know that TS is right but anyway, I think that most users will be frustrated and may blame TS for that.

This is misleading at best. Since Ember has its own entire home-brew class/inheritance system, unrelated to ES6 classes, with its own wrinkles such as pseudo-inheritance of methods inside an `actions` hash, and mixins, TS cannot deduce the shape of Ember objects, making this inapplicable.

This **could** be applicable to some future version of Ember which uses ES6 classes–which would be a major rearchitecting. However, any such future version of Ember is likely to (or should, anyway) use ES6 getters and setters instead of `this.get(‘a’)` and `this.set(‘a’, val)`, making this particular feature irrelevant.

Ember’s `get` also supports syntax such as `this.get(‘a.b.c’)`, which is impossible to support using this new feature.

Are object spread and keyof evaluated at compile-time or during run-time? I.e: would they be compatible with third-party javascript code, or must everything be typescript for them to work?

The reason i ask is that typescript historically has been very compatible with javascript code but you say that keyof is equivalent to “name” | “age” | “location”; which looks like a compile time constant. It could potentially also have big impact on performance: iterating Object.keys vs just a constant.

That release follows the wrong direction: keyOf operator, Mapped Types: as nice as these appear to java scripters, because they shortcut code, as bad they are: they are obscuring code:
I don’t want to dive into libraries to figure out what one or another function or operator is doing: I want to *see* that from code *at first glance*!
Before turning to such “quick-winning” special operators, you should have first fixed the problems with the findIndex method, a.o…

Could you please elaborate on what you meant by “keeping parity” in the async section? I would like to research this further to understand it better. Also, is there a code example of this new language feature?

We rewrote our emit pipeline to use a tree-transform model. This meant that there would be several stages, each which rewrites bits of syntax at a time (e.g. the ES2016 transform will rewrite the exponentiation operator, the ES2015 transform will rewrite arrow functions etc.)

This tends to be slower (as it exhausts memory & adds GC pressure from allocating new nodes, and requires some re-walking of the program’s trees). We wanted this not to be a cost imposed on every person, so we worked hard on keeping overhead low.

You can check out the results by running tsc with the –diagnostics flag, which will report differences in emit time.

TypeScript is basically JavaScript with optional static types. It builds on features from the newest version of JavaScript, and adds types on top.

TypeScript acts as a type-checker (so you can avoid errors), a language service (something that gives your editors cool features like completions), and a compiler (so that it can strip out the types and you can run your code in any browser).

If you were serious about TS and SASS, you would force browser vendors to support TS ans SASS directly.
The actively used versions of CSS and JS should never have gotten into browsers in the first place… They are a disgrace to engineering.

The same goes for HTML. It should function the same as XML and should be equal to . But no… That would be too sane for the crazy browser vendors…

It’s quite evident to me that web technologies are like toilet paper. Nothing fancy about them, just a way to wipe temporary problems away. Building on top of them makes no sense. Just replace those technologies already, even if you have to break the whole web (although that should not be necessary).

the problem is, that you cant do what you are saying. Browsers vendors are not going to break the whole internet, and are doing a great job of designing new backward compatible features, such as es2015+

For the rest of us living in the real world, building ontop of standards and extending them, as SASS and typescript do, seems a good approach

1 year ago

Jake

The real world is what you decide to make of it, not what you find in your plate by others.
If you accept having to deal with compilations for TS and SASS, the unnecessary bandwidth spending that comes with sending the “compiled” versions to the client, the problems dealing with mapping JS code back to the original TS code (same goes with SASS), the extra tools needed, the extra time spent, the extra load for your PC, the extra room you need to make in your head for yet another language that tries to defy common modern code syntaxes, etc, etc, then I give up. Obviously, you have no desire to be productive, simple and efficient at all – although, yes, TS and SASS is a step towards the right direction, but definitely not enough and definitely not an achievement compared to what the web really needs and what could be done. Excuse me for not bowing down to your “real world”, the world built by “geniuses” that made the worst scripting language ever, which had bugs even in its syntax, which had global functions more useless that the ones of C, which has no ability of doing even remotely reliable math calculations, which allowed people to shoot themselves in the foot 10 times more often than C++ did, which has specs that very often give browser vendors the freedom to do whatever they like (which is what they do anyway…), which requires at least 3-4 libraries in order to perform the most basic operations, which has a community that is totally confused and not sure yet (even after so many years) what the proper coding style and best practices should be, etc, etc.

And those are only for JS and only what flew through my mind in a couple of minutes. I will not even go into HTML and CSS, which suck as well.

> doing a great job of designing new backward compatible features

They are doing a horrible job actually.
The features are totally not prioritized correctly (I am not even sure if they can list all the required features, since I doubt these people code anything useful, any time in their life), they often deprecate features for which there is no alternative solution, etc, etc, etc.
As far for ES6, which is partially a patch for terribly wrong decisions of the past, the new features do not remove the old smelly baggage. And also, the set of functions available in JS remains the same, poor, unreliable and bad designed. Plus, most of the “new features” are things that every language on this earth had already at least 15 years back. So, JS is only starting to approach real modern languages, it’s not “getting new features”. Unless looping an array not in C-style code, getting the results you expect and using default function parameters, can be considered features that one could be proud of… So, it should be called es2003 instead. That’s the proximate date they are stuck in.

Long story short, if I did my work the same way as these people do theirs, I would have been fired 100 times already. No kidding. Too bad there is no-one to fire these people and we are stuck with them.

Good.
Now that TS becomes more mature, can you just make it use types the right way and convert:

name: string;

…to :

string name;

?
I hate this syntax because it is both ugly and it reminds me of languages that are dead (thank God for that).
Plus no developer out there is used to writing the type after the variable name.
If you change that, I might use TS.
If not, I will not use it.
So simple.
It’s the same as trying to replace the `new` operator in JS with `Object.create()`.
No sane developer will follow you.
And even if he does, he will hate you for it.
I guess that explains why JS developers have so much hate towards their community.