You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Decorators are special functions that can modify the behavior of classes, class methods, and class fields. Lit uses decorators to provide declarative APIs for things like registering elements, reactive properties, and queries.
12
+
Decorators are functions that can be used to declaratively annotate and modify the behavior of classes.
13
13
14
-
Decorators are a [stage 3 proposal](https://github.com/tc39/proposal-decorators) for addition to the ECMAScript standard. Currently no browsers implement decorators, but compilers like [Babel](https://babeljs.io/) and [TypeScript](https://www.typescriptlang.org/) provide support for an earlier version of the decorators proposal. Lit decorators work with Babel and TypeScript, and will be updated to work with the final specification when it's implemented in browsers.
14
+
Lit provides a set of optional decorators that enable declarative APIs for things like registering elements, defining reactive properties and query properties, or adding event options to event handler methods.
15
15
16
-
See the [Enabling decorators](#enabling-decorators) section for more information.
17
-
18
-
{% aside "info" %}
19
-
20
-
What does stage 3 mean?
21
-
22
-
Stage 3 means that the specification text is complete, and ready for browsers to implement. Once the specification has been implemented in multiple browsers, it can move to the final stage, stage 4, and be added to the ECMAScript standard. A stage 3 proposal can still change, but only if critical issues are discovered during implementation.
23
-
24
-
{% endaside %}
25
-
26
-
27
-
28
-
Lit supplies a set of decorators that reduce the amount of boilerplate code you need to write when defining a component. For example, the `@customElement` and `@property` decorators make a basic element definition more compact:
16
+
For example, the `@customElement` and `@property()` decorators let you register a custom element and define a reactive property in a compact, declarative way:
29
17
30
18
```ts
31
19
@customElement('my-element')
32
20
exportclassMyElementextendsLitElement {
33
-
@property() greeting ="Welcome";
34
-
@property() name ="Sally";
35
-
@property({type: Boolean}) emphatic =true;
36
-
//...
37
-
}
38
-
```
39
-
{#custom-element}
40
21
41
-
The `@customElement` decorator defines a custom element, equivalent to calling:
22
+
@property()
23
+
greeting ='Welcome';
42
24
43
-
```js
44
-
customElements.define('my-element', MyElement);
25
+
}
45
26
```
46
27
47
-
The `@property` decorator declares a reactive property.
28
+
{% aside "info" "no-header"%}
48
29
49
-
See [Reactive properties](/docs/v3/components/properties/) for more information about configuring properties.
30
+
Lit supports two different versions of the JavaScript decorators proposal – an early version supported by TypeScript that we refer to as _experimental decorators_ and a new and final version we refer to as _standard decorators_.
31
+
32
+
There are some small differences in usage between the two proposals (standard decorators often require the `accessor` keyword). Our code samples are written for experimental decorators because we recommend them for production at the moment.
33
+
34
+
See [Decorator versions](#decorator-versions) for more details.
35
+
36
+
{% endaside %}
50
37
51
38
## Built-in decorators
52
39
53
40
| Decorator | Summary | More Info |
54
41
|-----------|---------|--------------|
55
-
| {% api-v3 "@customElement" "customElement" %} | Defines a custom element |[Above](#custom-element)|
@@ -81,90 +68,125 @@ import {eventOptions} from 'lit/decorators/event-options.js';
81
68
82
69
To use decorators, you need to build your code with a compiler such as [TypeScript](#decorators-typescript) or [Babel](#decorators-babel).
83
70
84
-
In the future when decorators become a native web platform feature, this may no longer be necessary.
71
+
In the future when decorators are supported natively in browsers, this will no longer be necessary
85
72
86
73
### Using decorators with TypeScript { #decorators-typescript }
87
74
88
-
To use decorators with [TypeScript](https://www.typescriptlang.org/docs/handbook/decorators.html), enable the `experimentalDecorators` compiler option.
75
+
TypeScript supports both experimental decorators and standard decorators. We recommend that TypeScript developers use experimental decorators for now for [optimal compiler output](#compiler-output-considerations). If your project requires using standard decorators or setting `"useDefineForClassFields": true`, skip down to [migrating to standard decorators](#migrating-typescript-standard-decorators).
76
+
77
+
To use experimental decorators you must enable the `experimentalDecorators` compiler option.
89
78
90
-
You should also ensure that the `useDefineForClassFields` setting is `false`. Note, this should only be required when the `target` is set to `esnext` or greater, but it's recommended to explicitly ensure this setting is`false`.
79
+
You should also ensure that the `useDefineForClassFields` setting is `false`. Note, this is only required when the `target` is set to `ES2022` or greater, but it is recommended to explicitly set this to`false`.
91
80
92
81
```json
93
-
"experimentalDecorators": true,
94
-
"useDefineForClassFields": false,
82
+
// tsconfig.json
83
+
{
84
+
"compilerOptions": {
85
+
"experimentalDecorators": true,
86
+
"useDefineForClassFields": false,
87
+
}
88
+
}
95
89
```
96
90
97
91
Enabling `emitDecoratorMetadata` is not required and not recommended.
98
92
99
-
###Using decorators with Babel { #decorators-babel }
93
+
#### Migrating TypeScript experimental decorators to standard decorators { #migrating-typescript-standard-decorators }
100
94
101
-
If you're compiling JavaScript with [Babel](https://babeljs.io/docs/en/), you can enable decorators by adding the following plugins and settings:
95
+
Lit decorators are designed to support [standard decorator syntax](#standard-decorators) (using `accessor` on class field decorators) with TypeScript's experimental decorator mode.
Note, the `@babel/plugin-proposal-class-properties` may not be required with the latest versions of Babel.
107
-
108
-
To set up the plugins, add code like this to your Babel configuration:
97
+
This allows incremental migration off of experimental decorators starting with the addition of the `accessor` keyword to decorated properties without a change of behavior. Once all decorated class field use the `accessor` keyword, you can change your compiler options to complete the migration to standard decorators:
109
98
110
99
```json
111
-
"assumptions": {
112
-
"setPublicClassFields": true
113
-
},
114
-
"plugins": [
115
-
["@babel/plugin-proposal-decorators", {
116
-
"version": "2018-09",
117
-
"decoratorsBeforeExport": true
118
-
}],
119
-
["@babel/plugin-proposal-class-properties"]
120
-
]
100
+
// tsconfig.json
101
+
{
102
+
"compilerOptions": {
103
+
"experimentalDecorators": false, // default for TypeScript 5.0 and up
104
+
"useDefineForClassFields": true, // default when "target" is "ES2022" or higher
105
+
}
106
+
}
121
107
```
122
108
123
-
<divclass="alert alert-info">
124
-
125
-
Babel decorator support has been tested with `version: '2018-09'`. This is currently the default, but we recommend setting the version explicitly in case the default changes. Other versions ('2021-12' or 'legacy') are not supported, but this may change as Babel evolves. See the [Babel documentation](https://babeljs.io/docs/en/babel-plugin-proposal-decorators#options) if you want to experiment.
109
+
Note: The `accessor` keyword was introduced in TypeScript 4.9 and standard decorators with metadata require TypeScript ≥5.2.
126
110
127
-
</div>
111
+
### Using decorators with Babel { #decorators-babel }
128
112
129
-
### Using decorators with TypeScript and Babel
113
+
[Babel](https://babeljs.io/docs/en/) supports standard decorators with the [`@babel/plugin-proposal-decorators`](https://babeljs.io/docs/en/babel-plugin-proposal-decorators) plugin as of version 7.23. Babel does not support TypeScript experimental decorators, so you must use Lit decorators with [standard decorator syntax](#standard-decorators) using the `accessor` keyword on decorated class fields.
130
114
131
-
When using TypeScript with Babel, it's important to order the TypeScript transform before the decorators transform in your Babel config as follows:
115
+
Enable decorators by adding [`@babel/plugin-proposal-decorators`](https://babeljs.io/docs/en/babel-plugin-proposal-decorators) with these Babel configuration settings:
The `allowDeclareFields` setting is generally not needed, but it can be useful if you want to define a reactive property without using a decorator. For example,
126
+
Note: Lit decorators only work with `"version": "2023-05"`. Other versions, including the formerly supported `"2018-09"`, are not supported.
127
+
128
+
### Avoiding issues with class fields and decorators {#avoiding-issues-with-class-fields}
129
+
130
+
Standard [class fields](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/Public_class_fields) have a problematic interaction with declaring reactive properties. See [Avoiding issues with class fields when declaring properties](/docs/v3/components/properties/#avoiding-issues-with-class-fields) for more information.
131
+
132
+
When using decorators, transpiler settings for Babel and TypeScript must be configured correctly as shown in the sections above for [TypeScript](#decorators-typescript) and [Babel](#decorators-babel).
133
+
134
+
## Decorator versions
135
+
136
+
Decorators are a [stage 3 proposal](https://github.com/tc39/proposal-decorators) for addition to the ECMAScript standard. Compilers like [Babel](https://babeljs.io/) and [TypeScript](https://www.typescriptlang.org/) support decorators, though no browsers have implemented them yet. Lit decorators work with Babel and TypeScript, and will work in browsers when they implement them natively.
137
+
138
+
{% aside "info" %}
139
+
140
+
What does stage 3 mean?
141
+
142
+
It means that the specification text is complete, and ready for browsers to implement. Once the specification has been implemented in multiple browsers, it can move to the final stage, stage 4, and be added to the ECMAScript standard. A stage 3 proposal will only change if critical issues are discovered during implementation.
143
+
144
+
{% endaside %}
145
+
146
+
### Earlier decorator proposals
147
+
148
+
Before the TC39 proposal reached stage 3, compilers implemented earlier versions of the decorator specification.
149
+
150
+
Most notable of these is [TypeScript's _experimental decorators_](https://www.typescriptlang.org/docs/handbook/decorators.html) which Lit has supported since its inception and is our current recommendation for use.
151
+
152
+
Babel has also supported different versions of the specification over time as can be seen from the [`"version"` option of the decorator plugin](https://babeljs.io/docs/babel-plugin-proposal-decorators#version). In the past, Lit 2 has supported the `"2018-09"` version for Babel users but that has now been dropped in favor of the _standard_`"2023-05"` version described below.
153
+
154
+
### Standard decorators { #standard-decorators }
155
+
156
+
_Standard decorators_ is the version of decorators that has reached Stage 3 consensus at TC39, the body that defines ECMAScript/JavaScript.
157
+
158
+
Standard decorators are supported in TypeScript and Babel, with native browser coming in the near future.
159
+
160
+
The biggest difference between standard decorators and experimental decorators is that, for performance reasons, standard decorators cannot change the _kind_ of a class member – fields, accessors, and methods – being decorated and replaced, and will only produce the same kind of member.
161
+
162
+
Since many Lit decorators generate accessors, this means that the decorators need to be applied to accessors, not class fields.
163
+
164
+
To make this convenient, the standard decorator specification adds the `accessor` keyword to declare "auto-accessors":
165
+
166
+
```ts
167
+
classMyClass {
168
+
accessor foo =42;
169
+
}
170
+
```
171
+
172
+
Auto-accessors create a getter and setter pair that read and write from a private field. Decorators can then wrap these getters and setters.
173
+
174
+
Lit decorators that work on class fields with experimental decorators – such as `@property()`, `@state()`, `@query()`, etc. – must be applied to accessors or auto-accessors with standard decorators:
152
175
153
176
```ts
154
-
staticproperties= { foo: {} };
177
+
@customElement('my-element')
178
+
exportclassMyElementextendsLitElement {
155
179
156
-
declarefoo: string;
180
+
@property()
181
+
accessor greeting ='Welcome';
157
182
158
-
constructor() {
159
-
super();
160
-
this.foo='bar';
161
183
}
162
184
```
163
185
164
-
### Avoiding issues with class fields and decorators {#avoiding-issues-with-class-fields}
186
+
### Compiler output considerations
165
187
166
-
[Class fields](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/Public_class_fields) have a problematic interaction with declaring reactive properties. See [Avoiding issues with class fields when declaring properties](/docs/v3/components/properties/#avoiding-issues-with-class-fields) for more information.
188
+
Compiler output for standard decorators is unfortunately large due to the need to generate the accessors, private storage, and other objects that are part of the decorators API.
167
189
168
-
The current decorators [stage 3 proposal](https://github.com/tc39/proposal-decorators) does not directly address this issue, but it should be solved as the proposal evolves and matures.
190
+
So we recommend that users who wish to use decorators, if possible, use TypeScript experimental decorators for now.
169
191
170
-
When using decorators, transpiler settings for Babel and TypeScript must be configured correctly as shown in the sections above for [TypeScript](#decorators-typescript) and [Babel](#decorators-babel).
192
+
In the future the Lit team plans on adding decorator transforms to our optional Lit Compiler in order to compile standard decorators to a more compact compiler output. Native browser support will also eliminate the need for any compiler transforms at all.
0 commit comments