Skip to content

Commit da3cde1

Browse files
Add 3.1 content
1 parent 947d4f7 commit da3cde1

File tree

1 file changed

+132
-0
lines changed

1 file changed

+132
-0
lines changed

What's-new-in-TypeScript.md

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,135 @@
1+
# TypeScript 3.1
2+
3+
## Mapped types on tuples and arrays
4+
5+
In TypeScript 3.1, mapped object types<sup>[[1]](#ts-3-1-only-homomorphic)</sup> over tuples and arrays now produce new tuples/arrays, rather than creating a new type where members like `push()`, `pop()`, and `length` are converted.
6+
For example:
7+
8+
```ts
9+
type MapToPromise<T> = { [K in keyof T]: Promise<T[K]> };
10+
11+
type Coordinate = [number, number]
12+
13+
type PromiseCoordinate = MapToPromise<Coordinate>; // [Promise<number>, Promise<number>]
14+
```
15+
16+
`MapToPromise` takes a type `T`, and when that type is a tuple like `Coordinate`, only the numeric properties are converted.
17+
In `[number, number]`, there are two numerically named properties: `0` and `1`.
18+
When given a tuple like that, `MapToPromise` will create a new tuple where the `0` and `1` properties are `Promise`s of the original type.
19+
So the resulting type `PromiseCoordinate` ends up with the type `[Promise<number>, Promise<number>]`.
20+
21+
## Properties declarations on functions
22+
23+
TypeScript 3.1 brings the ability to define properties on function declarations and `const`-declared functons, simply by assigning to properties on these functions in the same scope.
24+
This allows us to write canonical JavaScript code without resorting to `namespace` hacks.
25+
For example:
26+
27+
```ts
28+
function readImage(path: string, callback: (err: any, image: Image) => void) {
29+
// ...
30+
}
31+
32+
readImage.sync = (path: string) => {
33+
const contents = fs.readFileSync(path);
34+
return decodeImageSync(contents);
35+
}
36+
```
37+
38+
Here, we have a function `readImage` which reads an image in a non-blocking asynchronous way.
39+
In addition to `readImage`, we've provided a convenience function on `readImage` itself called `readImage.sync`.
40+
41+
While ECMAScript exports are often a better way of providing this functionality, this new support allows code written in this style to "just work" TypeScript.
42+
Additionaly, this approach for property declarations allows us to express common patterns like `defaultProps` and `propTypes` on React stateless function components (SFCs).
43+
44+
```ts
45+
export const FooComponent => ({ name }) => (
46+
<div>Hello! I am {name}</div>
47+
);
48+
49+
FooComponent.defaultProps = {
50+
name: "(anonymous)",
51+
};
52+
```
53+
54+
<!--
55+
fs.readFile(path, (err, data) => {
56+
if (err) callback(err, undefined);
57+
else decodeImage(data, (err, image) => {
58+
if (err) callback(err, undefined);
59+
else callback(undefined, image);
60+
});
61+
});
62+
-->
63+
64+
------
65+
66+
<sup id="ts-3-1-only-homomorphic">[1]</sup> More specifically, homomorphic mapped types like in the above form.
67+
68+
## Version selection with `typesVersions`
69+
70+
Feedback from our community, as well as our own experience, has shown us that leveraging the newest TypeScript features while also accomodating users on the older versions are difficult.
71+
TypeScript introduces a new feature called `typesVersions` to help accomodate this model.
72+
73+
When using Node module resolution in TypeScript 3.1, when TypeScript cracks open a `package.json` file to figure out which files it needs to read, it first looks at a new field called `typesVersions`.
74+
A `package.json` with a `typesVersions` field might look like this:
75+
76+
```json
77+
{
78+
"name": "package-name",
79+
"version": "1.0",
80+
"types": "./index.d.ts",
81+
"typesVersions": {
82+
">=3.1": { "*": ["ts3.1/*"] }
83+
}
84+
}
85+
```
86+
87+
This `package.json` tells TypeScript to check whether the current version of TypeScript is running.
88+
If it's 3.1 or later, it figures out the path you've imported relative to the package, and reads from the package's `ts3.1` folder.
89+
That's what that `{ "*": ["ts3.1/*"] }` means - if you're familiar with path mapping today, it works exactly like that.
90+
91+
So in the above example, if we're importing from `"package-name"`, we'll try to resolve from `[...]/node_modules/package-name/ts3.1/index.d.ts` (and other relevant paths) when running in TypeScript 3.1.
92+
If we import from `package-name/foo`, we'll try to look for `[...]/node_modules/package-name/ts3.1/foo.d.ts` and `[...]/node_modules/package-name/ts3.1/foo/index.d.ts`.
93+
94+
What if we're not running in TypeScript 3.1 in this example?
95+
Well, if none of the fields in `typesVersions` get matched, TypeScript falls back to the `types` field, so here TypeScript 3.0 and earlier will be redirected to `[...]/node_modules/package-name/index.d.ts`.
96+
97+
### Matching behavior
98+
99+
The way that TypeScript decides on whether a version of the compiler & language matches is by using Node's [semver ranges](https://github.com/npm/node-semver#ranges).
100+
101+
### Multiple fields
102+
103+
`typesVersions` can support multiple fields where each field name is specified by the range to match on.
104+
105+
```json
106+
{
107+
"name": "package-name",
108+
"version": "1.0",
109+
"types": "./index.d.ts",
110+
"typesVersions": {
111+
">=3.2": { "*": ["ts3.2/*"] },
112+
">=3.1": { "*": ["ts3.1/*"] }
113+
}
114+
}
115+
```
116+
117+
Since ranges have the potential to overlap, determining which redirect applies is order-specific.
118+
That means in the above example, even though both the `>=3.2` and the `>=3.1` matchers support TypeScript 3.2 and above, reversing the order could have different behavior, so the above sample would not be equivalent to the following.
119+
120+
```json5
121+
{
122+
"name": "package-name",
123+
"version": "1.0",
124+
"types": "./index.d.ts",
125+
"typesVersions": {
126+
// NOTE: this doesn't work!
127+
">=3.1": { "*": ["ts3.1/*"] },
128+
">=3.2": { "*": ["ts3.2/*"] }
129+
}
130+
}
131+
```
132+
1133
# TypeScript 3.0
2134

3135
## Tuples in rest parameters and spread expressions

0 commit comments

Comments
 (0)