Skip to content
This repository was archived by the owner on Oct 12, 2022. It is now read-only.

Commit 9f11f3f

Browse files
committed
Review comments
1 parent 06ed494 commit 9f11f3f

File tree

1 file changed

+53
-100
lines changed

1 file changed

+53
-100
lines changed

pages/release notes/TypeScript 2.1.md

Lines changed: 53 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,13 @@ interface Person {
1515
let propName: keyof Person;
1616
```
1717

18-
The above is equivalent to having written out
18+
`keyof Person` is equivalent to having written out
1919

2020
```ts
2121
let propName: "name" | "age" | "location";
2222
```
2323

24-
This `keyof` operator is actually called an *index type query*.
24+
This `keyof` operator is called an *index type query*.
2525
It's like a query for keys on object types, the same way that `typeof` can be used as a query for types on values.
2626

2727
The dual of this is *indexed access types*, also called *lookup types*.
@@ -37,7 +37,7 @@ interface Person {
3737
let a: Person["age"];
3838
```
3939

40-
This is the same as saying that `n` gets the type of the `name` property in `Person`.
40+
This is the same as saying that `a` gets the type of the `name` property in `Person`.
4141
In other words:
4242

4343
```ts
@@ -51,7 +51,7 @@ When indexing with a union of literal types, the operator will look up each prop
5151
let nameOrAge: Person["name" | "age"];
5252
```
5353

54-
This pattern can be used with other parts of the type system to get type-safe lookups, serving users of libraries like Ember.
54+
You can use this pattern with other parts of the type system to get type-safe lookups, which is great if you use Ember or other frameworks like it.
5555

5656
```ts
5757
function get<T, K extends keyof T>(obj: T, propertyName: K): T[K] {
@@ -68,7 +68,8 @@ let oops = get(x, "wargarbl"); // error!
6868

6969
# Mapped Types
7070

71-
Let's say we have a `Person` type:
71+
One common task is to take an existing type and make each of its properties entirely optional.
72+
Let's say we have a `Person:
7273

7374
```ts
7475
interface Person {
@@ -78,8 +79,7 @@ interface Person {
7879
}
7980
```
8081

81-
Much of the time, we want to take an existing type and make each of its properties entirely optional.
82-
With `Person`, we might write the following:
82+
A partial verion of it can would be:
8383

8484
```ts
8585
interface PartialPerson {
@@ -89,78 +89,30 @@ interface PartialPerson {
8989
}
9090
```
9191

92-
Notice we had to define a completely new type.
93-
94-
Similarly, we might want to perform a shallow freeze of an object:
95-
96-
```ts
97-
interface FrozenPerson {
98-
readonly name: string;
99-
readonly age: number;
100-
readonly location: string;
101-
}
102-
```
103-
104-
Or we might want to create a related type where all the properties are `Promise`s.
92+
with Mapped types, `PartialPerson` can be written as a generalized transformation on the type `Person` as:
10593

10694
```ts
107-
interface BooleanifiedPerson {
108-
name: boolean;
109-
age: boolean;
110-
location: boolean;
111-
}
112-
```
113-
114-
Notice all this repetition - ideally, much of the same information in each variant of `Person` could have been shared.
115-
116-
Let's take a look at how we could write `BooleanifiedPerson` with a *mapped type*.
117-
118-
```ts
119-
type BooleanifiedPerson = {
120-
[P in "name" | "age" | "location"]: boolean
95+
type Partial<T> = {
96+
[P in keyof T]?: T[P];
12197
};
122-
```
12398

124-
Mapped types are produced by taking a union of literal types, and compute a set of properties for a new object type.
125-
They're like [list comprehensions in Python](https://docs.python.org/2/tutorial/datastructures.html#nested-list-comprehensions), but instead of producing new elements in a list, they produce new properties in a type.
126-
127-
In the above example, TypeScript uses each literal type in `"name" | "age" | "location"`, and produces a property of that name (e.g. properties named `name`, `age`, and `location`).
128-
`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`.
129-
130-
Right now, this new form doesn't look ideal, but we can use the `keyof` operator to cut down on the typing:
131-
132-
```ts
133-
type BooleanifiedPerson = {
134-
[P in keyof Person]: boolean
135-
};
99+
type PartialPerson = Partial<Person>;
136100
```
137101

138-
And then we can generalize it:
139-
140-
```ts
141-
type Booleanify<T> = {
142-
[P in keyof T]: boolean
143-
};
144-
145-
type BooleanifiedPerson = Booleanify<Person>;
146-
```
102+
Mapped types are produced by taking a union of literal types, and computing a set of properties for a new object type.
103+
They're like [list comprehensions in Python](https://docs.python.org/2/tutorial/datastructures.html#nested-list-comprehensions), but instead of producing new elements in a list, they produce new properties in a type.
147104

148-
With mapped types, we no longer have to create new partial or readonly variants of existing types either.
105+
In addition to `Partial`, Mapped Types can enable expressing many usueful transfomrations on types:
149106

150107
```ts
151-
// Keep types the same, but make every property optional.
152-
type Partial<T> = {
153-
[P in keyof T]?: T[P];
154-
};
155-
156108
// Keep types the same, but make each property to be read-only.
157109
type Readonly<T> = {
158110
readonly [P in keyof T]: T[P];
159111
};
160112

161-
// Same property names, but make the value a promise instead of a concreate one
162-
type Defered<T> = {
163-
readonly [P in keyof T]: Promise<T[P]>;
113+
// Same property names, but make the value a promise instead of a concrete one
114+
type Deferred<T> = {
115+
[P in keyof T]: Promise<T[P]>;
164116
};
165117

166118
// Wrap proxies around properties of T
@@ -169,26 +121,23 @@ type Proxify<T> = {
169121
};
170122
```
171123

172-
So instead of defining a completely new type like `PartialPerson`, we can just write `Partial<Person>`.
173-
Likewise, instead of repeating ourselves with `FrozenPerson`, we can just write `Readonly<Person>`!
174-
175124
## `Partial`, `Readonly`, `Record`, and `Pick`
176125

177-
`Partial` and `Readonly`, as described earlier, are very useful construct.
126+
`Partial` and `Readonly`, as described earlier, are very useful constructs.
178127
You can use them to describe some common JS routines like:
179128

180129
```ts
181130
function assign<T>(obj: T, props: Partial<T>): void;
182131
function freeze<T>(obj: T): Readonly<T>;
183132
```
184133

185-
For that, they are now included by default in the standard library.
134+
Because of that, they are now included by default in the standard library.
186135

187136
We're also including two other utility types as well: `Record` and `Pick`.
188137

189138
```ts
190139
// From T pick a set of properties K
191-
function pick<T, K extends keyof T>(obj: T, ...keys: K[]): Pick<T, K>;
140+
declare function pick<T, K extends keyof T>(obj: T, ...keys: K[]): Pick<T, K>;
192141

193142
const nameAndAgeOnly = pick(person, "name", "age"); // { name: string, age: number }
194143
```
@@ -211,7 +160,8 @@ Similar to array spread, spreading an object can be handy to get a shallow copy:
211160
let copy = { ...original };
212161
```
213162

214-
Similarly, you can merge several different objects so that in the following example, `merged` will have properties from `foo`, `bar`, and `baz`.
163+
Similarly, you can merge several different objects.
164+
In the following example, `merged` will have properties from `foo`, `bar`, and `baz`.
215165

216166
```ts
217167
let merged = { ...foo, ...bar, ...baz };
@@ -224,7 +174,7 @@ let obj = { x: 1, y: "string" };
224174
var newObj = {...obj, z: 3, y: 4}; // { x: number, y:number, x: number }
225175
```
226176

227-
The order of specifying spread operations decides what properties end up in the resulting object;
177+
The order of specifying spread operations determines what properties end up in the resulting object;
228178
properties in later spreads "win out" over previously created properties.
229179

230180
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:
@@ -283,12 +233,20 @@ Compiling and running the output should result in the correct behavior on an ES3
283233

284234
# Support for external helpers library (`tslib`)
285235

286-
TypeScript injects a handful of helper functions such as `__extends` for inheritance, `__assign` for spread operator in JSX, and `__awaiter` for async functions.
287-
Previously there were two options either 1. inject helpers in *every* file that needs them or 2. no helpers at all with `--noEmitHelpers`.
236+
TypeScript injects a handful of helper functions such as `__extends` for inheritance, `__assign` for spread operator in object literals and JSX elements, and `__awaiter` for async functions.
237+
238+
Previously there were two options either:
239+
240+
1. inject helpers in *every* file that needs them, or
241+
2. no helpers at all with `--noEmitHelpers`.
242+
243+
The two options left more to be desired;
244+
bundling the helpers in every file was a pain point for customers trying to keep their package size small.
245+
And not including helpers, meant customers had to maintain their own helpers library.
288246

289247
TypeScript 2.1 allows for including these files in your project once in a separate module, and the compiler will emit imports to them as needed.
290248

291-
First, install the [`tslib`](https://github.com/Microsoft/tslib):
249+
First, install the [`tslib`](https://github.com/Microsoft/tslib) utility library:
292250

293251
```sh
294252
npm install tslib
@@ -300,17 +258,13 @@ Second, compile your files using `--importHelpers`:
300258
tsc --module commonjs --importHelpers a.ts
301259
```
302260

303-
##### Example
304-
305-
For input using the object rest `__assign` helper:
261+
So given the following input, the resulting `.js` file will include an import to `tslib` and use the `__assign` helper from it instead of inlining it.
306262

307263
```ts
308264
export const o = { a: 1, name: "o" };
309265
export const copy = { ...o };
310266
```
311267

312-
The resulting `.js` file will include an import to `tslib` and use the `__assign` helper from it instead of inlining it.
313-
314268
```js
315269
"use strict";
316270
var tslib_1 = require("tslib");
@@ -325,7 +279,7 @@ This was to avoid typos and prevent users from using modules incorrectly.
325279

326280
However, a lot of the time, you might just want to import an existing module that may not have its own `.d.ts` file.
327281
Previously this was an error.
328-
Starting with TypeScript 2.1 this should get much easier.
282+
Starting with TypeScript 2.1 this is now much easier.
329283

330284
With TypeScript 2.1, you can import a JavaScript module without needing a type declaration.
331285
A type declaration (such as `declare module "foo" { ... }` or `node_modules/@types/foo`) still takes priority if it exists.
@@ -339,9 +293,19 @@ An import to a module with no declaration file will still be flagged as an error
339293
import { x } from "asdf";
340294
```
341295

296+
# Support for `--target ES2016`, `--target ES2017` and `--target ESNext`
297+
298+
TypeScript 2.1 supports three new target values `--target ES2016`, `--target ES2017` and `--target ESNext`.
299+
300+
Using target `--target ES2016` will instruct the compiler not to transform ES2016-specific features, e.g. `**` operator.
301+
302+
Similarly, `--target ES2017` will instruct the compiler not to transform ES2017-specific features like `async`/`await`.
303+
304+
`--target ESNext` targets latest supported [ES proposed features](https://github.com/tc39/proposals).
305+
342306
# Improved `any` Inference
343307

344-
Previously, if TypeScript can't figure out the type of a variable, it will choose the `any` type.
308+
Previously, if TypeScript couldn't figure out the type of a variable, it would choose the `any` type.
345309

346310
```ts
347311
let x; // implicitly 'any'
@@ -380,7 +344,7 @@ x.toLowerCase();
380344
The same sort of tracking is now also done for empty arrays.
381345

382346
A variable declared with no type annotation and an initial value of `[]` is considered an implicit `any[]` variable.
383-
Each following `x.push(value)`, `x.unshift(value)` or `x[n] = value` operation _evolves_ the type of the variable in accordance with what elements are added to it.
347+
However, each subsequent `x.push(value)`, `x.unshift(value)` or `x[n] = value` operation *evolves* the type of the variable in accordance with what elements are added to it.
384348

385349
``` ts
386350
function f1() {
@@ -406,7 +370,7 @@ function f2() {
406370
## Implicit any errors
407371

408372
One great benefit of this is that you'll see *way fewer* implicit `any` errors when running with `--noImplicitAny`.
409-
Implicit `any` errors are only reported when the compiler is unable to know the type of a available without a type annotation.
373+
Implicit `any` errors are only reported when the compiler is unable to know the type of a variable without a type annotation.
410374

411375
##### Example
412376

@@ -423,7 +387,7 @@ function f3() {
423387
# Better inference for literal types
424388

425389
String, numeric and boolean literal types (e.g. `"abc"`, `1`, and `true`) were previously inferred only in the presence of an explicit type annotation.
426-
Starting with TypeScript 2.1, literal types are *always* inferred by default.
390+
Starting with TypeScript 2.1, literal types are *always* inferred for `const` variables and `readonly` properties.
427391

428392
The type inferred for a `const` variable or `readonly` property without a type annotation is the type of the literal initializer.
429393
The type inferred for a `let` variable, `var` variable, parameter, or non-`readonly` property with an initializer and no type annotation is the widened literal type of the initializer.
@@ -432,7 +396,6 @@ Where the widened type for a string literal type is `string`, `number` for numer
432396
##### Example
433397

434398
```ts
435-
436399
const c1 = 1; // Type 1
437400
const c2 = c1; // Type 1
438401
const c3 = "abc"; // Type "abc"
@@ -462,7 +425,7 @@ let v2 = c2; // Type "hello"
462425

463426
# Use returned values from super calls as 'this'
464427

465-
In ES2015, constructors which return a value (which is an object) implicitly substitute the value of `this` for any callers of `super()`.
428+
In ES2015, constructors which return an object implicitly substitute the value of `this` for any callers of `super()`.
466429
As a result, it is necessary to capture any potential return value of `super()` and replace it with `this`.
467430
This change enables working with [Custom Elements](https://w3c.github.io/webcomponents/spec/custom/#htmlelement-constructor), which takes advantage of this to initialize browser-allocated elements with user-written constructors.
468431

@@ -509,9 +472,9 @@ Just a few configuration options change between these two targets, and maintaini
509472
TypeScript 2.1 supports inheriting configuration using `extends`, where:
510473

511474
* `extends` is a new top-level property in `tsconfig.json` (alongside `compilerOptions`, `files`, `include`, and `exclude`).
512-
* `extends`' value is a string containing a path to another configuration file to inherit from.
475+
* The value of `extends` must be a string containing a path to another configuration file to inherit from.
513476
* The configuration from the base file are loaded first, then overridden by those in the inheriting config file.
514-
* If a circularity is encountered, we report an error.
477+
* Circularity between configuration files is not allowed.
515478
* `files`, `include` and `exclude` from the inheriting config file *overwrite* those from the base config file.
516479
* All relative paths found in the configuration file will be resolved relative to the configuration file they originated in.
517480

@@ -560,13 +523,3 @@ Invoking the compiler with `--alwaysStrict` causes:
560523

561524
Modules are parsed automatically in strict mode.
562525
The new flag is recommended for non-module code.
563-
564-
# Support for `--target ES2016`, `--target ES2017` and `--target ESNext`
565-
566-
TypeScript 2.1 supports three new target values `--target ES2016`, `--target ES2017` and `--target ESNext`.
567-
568-
Using target `--target ES2016` will instruct the compiler not to transform ES2016-specific features, e.g. `**` operator.
569-
570-
Similarly, `--target ES2017` will instruct the compiler not to transform ES2017-specific features like `async`/`await`.
571-
572-
`--target ESNext` targets latest supported [ES proposed features](https://github.com/tc39/proposals).

0 commit comments

Comments
 (0)