lwc icon indicating copy to clipboard operation
lwc copied to clipboard

feat(types): update types for v7

Open wjhsf opened this issue 1 year ago • 5 comments

Details

Things that changed

  • lwc/index.js just re-exports from @lwc/engine-dom. lwc/index.d.ts contains 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 experimentalDecorators flag in playground/tsconfig.json and run yarn build for both options.
  • 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.host to HTMLElement instead of the broader Element, since we know that this will always be true.
  • In v6, WireAdapter and WireAdapterConstructor were generic when imported from lwc, 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

wjhsf avatar Apr 30 '24 18:04 wjhsf

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.

nolanlawson avatar Apr 30 '24 21:04 nolanlawson

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.

nolanlawson avatar Apr 30 '24 21:04 nolanlawson

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 avatar May 17 '24 15:05 wjhsf

@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.

nolanlawson avatar May 17 '24 16:05 nolanlawson

  1. We need to have at least some minimal tests, preferably in the lwc package, 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). 🤷

  1. We should figure out some way to make createElement("x-foo", { is: Foo }).bar work (where bar is some @api-decorated property). There has to be some TypeScript jujitsu that can accomplish this.

wjhsf avatar May 20 '24 16:05 wjhsf

Check types test is failing ^

nolanlawson avatar Jun 04 '24 21:06 nolanlawson

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.

wjhsf avatar Jun 11 '24 18:06 wjhsf

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.

nolanlawson avatar Jun 11 '24 20:06 nolanlawson

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.

wjhsf avatar Jun 11 '24 20:06 wjhsf

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.

nolanlawson avatar Jun 12 '24 21:06 nolanlawson

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.

nolanlawson avatar Jun 18 '24 17:06 nolanlawson

/nucleus ignore --reason 'known typescript breaking changes for LWC v7'

nolanlawson avatar Jun 19 '24 19:06 nolanlawson