|
| 1 | +# TypeScript 4.8 |
| 2 | + |
| 3 | +## Decorators are placed on `modifiers` on TypeScript's Syntax Trees |
| 4 | + |
| 5 | +The current direction of decorators in TC39 means that TypeScript will have to handle a break in terms of placement of decorators. |
| 6 | +Previously, TypeScript assumed decorators would always be placed prior to all keywords/modifiers. |
| 7 | +For example |
| 8 | + |
| 9 | +```ts |
| 10 | +@decorator |
| 11 | +export class Foo { |
| 12 | + // ... |
| 13 | +} |
| 14 | +``` |
| 15 | + |
| 16 | +Decorators as currently proposed do not support this syntax. |
| 17 | +Instead, the `export` keyword must precede the decorator. |
| 18 | + |
| 19 | +```ts |
| 20 | +export @decorator class Foo { |
| 21 | + // ... |
| 22 | +} |
| 23 | +``` |
| 24 | + |
| 25 | +Unfortunately, TypeScript's trees are *concrete* rather than *abstract*, and our architecture expects syntax tree node fields to be entirely ordered before or after each other. |
| 26 | +To support both legacy decorators and decorators as proposed, TypeScript will have to gracefully parse, and intersperse, modifiers and decorators. |
| 27 | + |
| 28 | +To do this, it exposes a new type alias called `ModifierLike` which is a `Modifier` or a `Decorator`. |
| 29 | + |
| 30 | +```ts |
| 31 | +export type ModifierLike = Modifier | Decorator; |
| 32 | +``` |
| 33 | + |
| 34 | +Decorators are now placed in the same field as `modifiers` which is now a `NodeArray<ModifierLike>` when set, and the entire field is deprecated. |
| 35 | + |
| 36 | +```diff |
| 37 | +- readonly modifiers?: NodeArray<Modifier> | undefined; |
| 38 | ++ /** |
| 39 | ++ * @deprecated ... |
| 40 | ++ * Use `ts.canHaveModifiers()` to test whether a `Node` can have modifiers. |
| 41 | ++ * Use `ts.getModifiers()` to get the modifiers of a `Node`. |
| 42 | ++ * ... |
| 43 | ++ */ |
| 44 | ++ readonly modifiers?: NodeArray<ModifierLike> | undefined; |
| 45 | +``` |
| 46 | + |
| 47 | +All existing `decorators` properties have been marked as deprecated and will always be `undefined` if read. |
| 48 | +The type has also been changed to `undefined` so that existing tools know to handle them correctly. |
| 49 | + |
| 50 | +```diff |
| 51 | +- readonly decorators?: NodeArray<Decorator> | undefined; |
| 52 | ++ /** |
| 53 | ++ * @deprecated ... |
| 54 | ++ * Use `ts.canHaveDecorators()` to test whether a `Node` can have decorators. |
| 55 | ++ * Use `ts.getDecorators()` to get the decorators of a `Node`. |
| 56 | ++ * ... |
| 57 | ++ */ |
| 58 | ++ readonly decorators?: undefined; |
| 59 | +``` |
| 60 | + |
| 61 | +To avoid all deprecation warnings and other issues, TypeScript now exposes four new functions. |
| 62 | +There are individual predicates for testing whether a node has support modifiers and decorators, along with respective accessor functions for grabbing them. |
| 63 | + |
| 64 | +```ts |
| 65 | +function canHaveModifiers(node: Node): node is HasModifiers; |
| 66 | +function getModifiers(node: HasModifiers): readonly Modifier[] | undefined; |
| 67 | + |
| 68 | +function canHaveDecorators(node: Node): node is HasDecorators; |
| 69 | +function getDecorators(node: HasDecorators): readonly Decorator[] | undefined; |
| 70 | +``` |
| 71 | + |
| 72 | +As an example of how to access modifiers off of a node, you can write |
| 73 | + |
| 74 | +```ts |
| 75 | +const modifiers = canHaveModifiers(myNode) ? getModifiers(myNode) : undefined; |
| 76 | +``` |
| 77 | + |
| 78 | +With the note that each call to `getModifiers` and `getDecorators` may allocate a new array. |
| 79 | + |
| 80 | +For more information, see changes around |
| 81 | + |
| 82 | +* [the restructuring of our tree nodes](https://github.com/microsoft/TypeScript/pull/49089) |
| 83 | +* [the deprecations](https://github.com/microsoft/TypeScript/pull/50343) |
| 84 | +* [exposing the predicate functions](https://github.com/microsoft/TypeScript/pull/50399) |
| 85 | + |
1 | 86 | # TypeScript 4.7
|
2 | 87 |
|
3 | 88 | - `resolveTypeReferenceDirectives` (both the services and global ts version) now accept an array of `FileReference`s as a first argument. If you reimplement `resolveTypeReferenceDirectives`, you need to handle both the `string[]` and `FileReference[]` cases now.
|
|
0 commit comments