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

Commit a12ad03

Browse files
Merge pull request #624 from Microsoft/2.4Update
2.4 update
2 parents 21c1875 + 166fe07 commit a12ad03

File tree

2 files changed

+166
-0
lines changed

2 files changed

+166
-0
lines changed

pages/Compiler Options.md

+1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ Option | Type | Default
4646
`--noImplicitUseStrict` | `boolean` | `false` | Do not emit `"use strict"` directives in module output.
4747
`--noLib` | `boolean` | `false` | Do not include the default library file (`lib.d.ts`).
4848
`--noResolve` | `boolean` | `false` | Do not add triple-slash references or module import targets to the list of compiled files.
49+
`--noStrictGenericChecks` | `boolean` | `false` | Disable strict checking of generic signatures in function types.
4950
`--noUnusedLocals` | `boolean` | `false` | Report errors on unused locals.
5051
`--noUnusedParameters` | `boolean` | `false` | Report errors on unused parameters.
5152
~~`--out`~~ | `string` | | DEPRECATED. Use `--outFile` instead.

pages/release notes/TypeScript 2.4.md

+165
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
# TypeScript 2.4
2+
3+
## Dynamic Import Expressions
4+
5+
Dynamic `import` expressions are a new feature and part of ECMAScript that allows users to asynchronously request a module at any arbitrary point in your program.
6+
7+
This means that you can conditionally and lazily import other modules and libraries.
8+
For example, here's an `async` function that only imports a utility library when it's needed:
9+
10+
```ts
11+
async function getZipFile(name: string, files: File[]): Promise<File> {
12+
const zipUtil = await import('./utils/create-zip-file');
13+
const zipContents = await zipUtil.getContentAsBlob(files);
14+
return new File(zipContents, name);
15+
}
16+
```
17+
18+
Many bundlers have support for automatically splitting output bundles based on these `import` expressions, so consider using this new feature with the `esnext` module target.
19+
20+
## String Enums
21+
22+
TypeScript 2.4 now allows enum members to contain string initializers.
23+
24+
```ts
25+
enum Colors {
26+
Red = "RED",
27+
Green = "GREEN",
28+
Blue = "BLUE",
29+
}
30+
```
31+
32+
The caveat is that string-initialized enums can't be reverse-mapped to get the original enum member name.
33+
In other words, you can't write `Colors["RED"]` to get the string `"Red"`.
34+
35+
## Improved inference for generics
36+
37+
TypeScript 2.4 introduces a few wonderful changes around the way generics are inferred.
38+
39+
### Return types as inference targets
40+
41+
For one, TypeScript can now make inferences for the return type of a call.
42+
This can improve your experience and catch errors.
43+
Something that now works:
44+
45+
```ts
46+
function arrayMap<T, U>(f: (x: T) => U): (a: T[]) => U[] {
47+
return a => a.map(f);
48+
}
49+
50+
const lengths: (a: string[]) => number[] = arrayMap(s => s.length);
51+
```
52+
53+
As an example of new errors you might spot as a result:
54+
55+
```ts
56+
let x: Promise<string> = new Promise(resolve => {
57+
resolve(10);
58+
// ~~ Error!
59+
});
60+
```
61+
62+
### Type parameter inference from contextual types
63+
64+
Prior to TypeScript 2.4, in the following example
65+
66+
```ts
67+
let f: <T>(x: T) => T = y => y;
68+
```
69+
70+
`y` would have the type `any`.
71+
This meant the program would type-check, but you could technically do anything with `y`, such as the following:
72+
73+
```ts
74+
let f: <T>(x: T) => T = y => y() + y.foo.bar;
75+
```
76+
77+
That last example isn't actually type-safe.
78+
79+
In TypeScript 2.4, the function on the right side implicitly *gains* type parameters, and `y` is inferred to have the type of that type-parameter.
80+
81+
If you use `y` in a way that the type parameter's constraint doesn't support, you'll correctly get an error.
82+
In this case, the constraint of `T` was (implicitly) `{}`, so the last example will appropriately fail.
83+
84+
### Stricter checking for generic functions
85+
86+
TypeScript now tries to unify type parameters when comparing two single-signature types.
87+
As a result, you'll get stricter checks when relating two generic signatures, and may catch some bugs.
88+
89+
```ts
90+
type A = <T, U>(x: T, y: U) => [T, U];
91+
type B = <S>(x: S, y: S) => [S, S];
92+
93+
function f(a: A, b: B) {
94+
a = b; // Error
95+
b = a; // Ok
96+
}
97+
```
98+
99+
## Strict contravariance for callback parameters
100+
101+
TypeScript has always compared parameters in a bivariant way.
102+
There are a number of reasons for this, but by-and-large this was not been a huge issue for our users until we saw some of the adverse effects it had with `Promise`s and `Observable`s.
103+
104+
TypeScript 2.4 introduces tightens this up when relating two callback types. For example:
105+
106+
```ts
107+
interface Mappable<T> {
108+
map<U>(f: (x: T) => U): Mappable<U>;
109+
}
110+
111+
declare let a: Mappable<number>;
112+
declare let b: Mappable<string | number>;
113+
114+
a = b;
115+
b = a;
116+
```
117+
118+
Prior to TypeScript 2.4, this example would succeed.
119+
When relating the types of `map`, TypeScript would bidirectionally relate their parameters (i.e. the type of `f`).
120+
When relating each `f`, TypeScript would also bidirectionally relate the type of *those* parameters.
121+
122+
When relating the type of `map` in TS 2.4, the language will check whether each parameter is a callback type, and if so, it will ensure that those parameters are checked in a contravariant manner with respect to the current relation.
123+
124+
In other words, TypeScript now catches the above bug, which may be a breaking change for some users, but will largely be helpful.
125+
126+
## Weak Type Detection
127+
128+
TypeScript 2.4 introduces the concept of "weak types".
129+
Any type that contains nothing but a set of all-optional properties is considered to be *weak*.
130+
For example, this `Options` type is a weak type:
131+
132+
```ts
133+
interface Options {
134+
data?: string,
135+
timeout?: number,
136+
maxRetries?: number,
137+
}
138+
```
139+
140+
In TypeScript 2.4, it's now an error to assign anything to a weak type when there's no overlap in properties.
141+
For example:
142+
143+
```ts
144+
function sendMessage(options: Options) {
145+
// ...
146+
}
147+
148+
const opts = {
149+
payload: "hello world!",
150+
retryOnFail: true,
151+
}
152+
153+
// Error!
154+
sendMessage(opts);
155+
// No overlap between the type of 'opts' and 'Options' itself.
156+
// Maybe we meant to use 'data'/'maxRetries' instead of 'payload'/'retryOnFail'.
157+
```
158+
159+
You can think of this as TypeScript "toughening up" the weak guarantees of these types to catch what would otherwise be silent bugs.
160+
161+
Since this is a breaking change, you may need to know about the workarounds which are the same as those for strict object literal checks:
162+
163+
1. Declare the properties if they really do exist.
164+
2. Add an index signature to the weak type (i.e. `[propName: string]: {}`).
165+
3. Use a type assertion (i.e. `opts as Options`).

0 commit comments

Comments
 (0)