lwc
lwc copied to clipboard
feat(types): update types for v7
Details
Things that changed
lwc/index.jsjust re-exports from@lwc/engine-dom.lwc/index.d.tscontains numerous outdated types. This removes them. Fixes #3598.- Our decorators currently use the type signature for TypeScript's experimental decorators. But TypeScript introduced new decorators in v5 that are compliant with the proposed spec. This updates the signature of our decorators to support both formats.
- To validate that the signatures work with both kinds of decorators, check out #4178 (or fbc1fe5cf0f4b6faffc319b3e1d5e5a9b99c3121, if the latest commit is broken). Toggle the
experimentalDecoratorsflag inplayground/tsconfig.jsonand runyarn buildfor both options.
- To validate that the signatures work with both kinds of decorators, check out #4178 (or fbc1fe5cf0f4b6faffc319b3e1d5e5a9b99c3121, if the latest commit is broken). Toggle the
- Added a new helper,
lwc/html, that provides the correct types for HTML templates. Just import it once in your project (or add it to your tsconfig includes) to get HTML templates to be correctly typed. - Narrowed
this.template.hosttoHTMLElementinstead of the broaderElement, since we know that this will always be true. - In v6,
WireAdapterandWireAdapterConstructorwere generic when imported fromlwc, but not when imported from@lwc/engine-core. I updated the type definitions to be generic with defaults, so that both imports should continue to work unmodified.
Things that might break
AKA things that I saw break in our nucleus downstreams.
| Breakage | Fixage |
|---|---|
HTML imports (import myComponent from './my-component.html') |
Import lwc/html or lwc/@engine-dom/html somewhere in your project. |
StringKeyedRecord |
Replace with Record<string, any> or something better. |
ContextValue |
Renamed to WireContextValue, but it's really just Record<string, any>, so maybe use something better. |
ContextConsumer |
Renamed to WireContextConsumer |
Contextualizer |
Renamed to WireContextProvider |
createElement |
Use type assertion to cast to HTMLElement & MyComponentApiDecoratedProps. You have to define your own interface to get the @api decorated props, because TypeScript can't detect that. (You can use your component class, but that includes all component and LightningElement props, not just component @api decorated props, so it's not ideal.) |
this.template is possibly undefined |
Use optional chaining (?.) or non-null assertion (!.) |
Cannot find name ClassMemberDecoratorContext (or other decorator type) |
Use TypeScript v5.4.5 |
| Other type errors? | Use TypeScript v5.4.5 |
Does this pull request introduce a breaking change?
- 💔 Yes, it does introduce a breaking change.
Does this pull request introduce an observable change?
- 🤞 No, it does not introduce an observable change.
- 🔬 Yes, it does include an observable change.
GUS work item
I'm supportive of this PR in general, so that we can finally resolve #3598. If there are breakages then that's okay, as long as the breakages make sense.
Here is a list of downstream breakages. Let's take some time to make sure these are all reasonable.
Also: I'm wondering if it's about time we added some real TypeScript tests somewhere. Nothing too fancy, just something to confirm that the types compile the way we expect them to compile. A good place for this would probably the barrel lwc package, since that's where people tend to import from.
Also: I'm wondering if it's about time we added some real TypeScript tests somewhere. Nothing too fancy, just something to confirm that the types compile the way we expect them to compile. A good place for this would probably the barrel lwc package, since that's where people tend to import from.
Any test written in TypeScript is implicitly a test of the types, as changing the types will cause the tests to fail. So, provided we write enough tests in TypeScript, we get type coverage for free.
@wjhsf The challenge there is that, historically, we don't have any TS-based browser tests in this repo. All our Karma tests are in JS, and our Jest tests (which do use TS) don't use JSDOM or browser APIs.
So for example, we're not testing this kind of code anywhere:
export default class extends LightningElement {
static renderMode = 'light' // should fail TS
renderedCallback() {
this.doesNotExist = foo // should fail TS
this.setAttribute(123, false) // should fail TS
}
}
I'm wondering if it would make sense to have a "hello world" Jest+JSDOM test in the lwc package just to test the types. Or tsd or something.
- We need to have at least some minimal tests, preferably in the
lwcpackage, that test the types our users are likely to use.
I added it under @lwc/integration-types so that we have more flexibility with the setup (particularly tsconfig settings). 🤷
- We should figure out some way to make
createElement("x-foo", { is: Foo }).barwork (wherebaris some@api-decorated property). There has to be some TypeScript jujitsu that can accomplish this.
✅
Check types test is failing ^
Bikeshed: what do you think about import '@lwc/types' rather than import 'lwc/types'? I wonder if the former would be more familiar to JS developers (similar to @babel/types, @typescript-eslint/types, etc.).
That depends, I guess, on how often users import lwc/ sub-packages vs @lwc/ scoped packages.
That depends, I guess, on how often users import
lwc/sub-packages vs@lwc/scoped packages.
Historically, people always import @lwc/*. I haven't even seen any uses of lwc/* in the wild since it requires ESM.
Nucleus Failures: Everything looks okay!
| Project | Status | Description |
|---|---|---|
communities/webruntime |
👍 | Failing due to other changes; passes type checking at install/build/unit test. |
ui-externalservices-builder-components |
🐌 | Not on LWC v6. |
Skilling-and-Enablement/storybook-utils |
✅ | Trivial breakage, easily fixed post-release. |
salesforce-experience-platform-emu/lwr-recipes |
✅ | Looks like it's mostly renderMode and a sprinkling of ?.. |
automation-platform/ui-interaction-explorer-components |
✅ | Mostly ?. and breakages related to defining their own signature for createElement. |
Skilling-and-Enablement/ui-external-enablement |
✅ | Easy fixes |
salesforce-experience-platform-emu/lwr |
👍 | I didn't do a deep dive into this one, but it doesn't seem like there's much by way of new breakages. |
BTW one thing we will do with v7 is have some release notes ala v6.0.0. Looks like the markdown above already lists the majority of the breaking changes and resolutions, but if you have any more, feel free to add.
Follow-up from dev sync: it would be great to detect static renderMode = 'shadow' and static renderMode = 'light' and detect whether this.template is non-null or null in each case.
This check can't be perfect, due to subclasses/mixins, but we can do the right thing for the ~95% case.
/nucleus ignore --reason 'known typescript breaking changes for LWC v7'