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

Commit de12242

Browse files
Add release notes for TS 3.1.
1 parent 3bf4102 commit de12242

File tree

1 file changed

+129
-0
lines changed

1 file changed

+129
-0
lines changed

pages/release notes/TypeScript 3.1.md

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
# Mapped types on tuples and arrays
2+
3+
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.
4+
For example:
5+
6+
```ts
7+
type MapToPromise<T> = { [K in keyof T]: Promise<T[K]> };
8+
9+
type Coordinate = [number, number]
10+
11+
type PromiseCoordinate = MapToPromise<Coordinate>; // [Promise<number>, Promise<number>]
12+
```
13+
14+
`MapToPromise` takes a type `T`, and when that type is a tuple like `Coordinate`, only the numeric properties are converted.
15+
In `[number, number]`, there are two numerically named properties: `0` and `1`.
16+
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.
17+
So the resulting type `PromiseCoordinate` ends up with the type `[Promise<number>, Promise<number>]`.
18+
19+
# Properties declarations on functions
20+
21+
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.
22+
This allows us to write canonical JavaScript code without resorting to `namespace` hacks.
23+
For example:
24+
25+
```ts
26+
function readImage(path: string, callback: (err: any, image: Image) => void) {
27+
// ...
28+
}
29+
30+
readImage.sync = (path: string) => {
31+
const contents = fs.readFileSync(path);
32+
return decodeImageSync(contents);
33+
}
34+
```
35+
36+
Here, we have a function `readImage` which reads an image in a non-blocking asynchronous way.
37+
In addition to `readImage`, we've provided a convenience function on `readImage` itself called `readImage.sync`.
38+
39+
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.
40+
Additionaly, this approach for property declarations allows us to express common patterns like `defaultProps` and `propTypes` on React stateless function components (SFCs).
41+
42+
```ts
43+
export const FooComponent => ({ name }) => (
44+
<div>Hello! I am {name}</div>
45+
);
46+
47+
FooComponent.defaultProps = {
48+
name: "(anonymous)",
49+
};
50+
```
51+
52+
<!--
53+
fs.readFile(path, (err, data) => {
54+
if (err) callback(err, undefined);
55+
else decodeImage(data, (err, image) => {
56+
if (err) callback(err, undefined);
57+
else callback(undefined, image);
58+
});
59+
});
60+
-->
61+
62+
------
63+
64+
<sup id="ts-3-1-only-homomorphic">[1]</sup> More specifically, homomorphic mapped types like in the above form.
65+
66+
# Version selection with `typesVersions`
67+
68+
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.
69+
TypeScript introduces a new feature called `typesVersions` to help accomodate these scenarios.
70+
71+
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`.
72+
A `package.json` with a `typesVersions` field might look like this:
73+
74+
```json
75+
{
76+
"name": "package-name",
77+
"version": "1.0",
78+
"types": "./index.d.ts",
79+
"typesVersions": {
80+
">=3.1": { "*": ["ts3.1/*"] }
81+
}
82+
}
83+
```
84+
85+
This `package.json` tells TypeScript to check whether the current version of TypeScript is running.
86+
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.
87+
That's what that `{ "*": ["ts3.1/*"] }` means - if you're familiar with path mapping today, it works exactly like that.
88+
89+
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.
90+
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`.
91+
92+
What if we're not running in TypeScript 3.1 in this example?
93+
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`.
94+
95+
## Matching behavior
96+
97+
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).
98+
99+
## Multiple fields
100+
101+
`typesVersions` can support multiple fields where each field name is specified by the range to match on.
102+
103+
```json
104+
{
105+
"name": "package-name",
106+
"version": "1.0",
107+
"types": "./index.d.ts",
108+
"typesVersions": {
109+
">=3.2": { "*": ["ts3.2/*"] },
110+
">=3.1": { "*": ["ts3.1/*"] }
111+
}
112+
}
113+
```
114+
115+
Since ranges have the potential to overlap, determining which redirect applies is order-specific.
116+
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.
117+
118+
```json5
119+
{
120+
"name": "package-name",
121+
"version": "1.0",
122+
"types": "./index.d.ts",
123+
"typesVersions": {
124+
// NOTE: this doesn't work!
125+
">=3.1": { "*": ["ts3.1/*"] },
126+
">=3.2": { "*": ["ts3.2/*"] }
127+
}
128+
}
129+
```

0 commit comments

Comments
 (0)