Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Type definition for createElement is inaccurate #4292

Open
wjhsf opened this issue Jun 13, 2024 · 0 comments
Open

Type definition for createElement is inaccurate #4292

wjhsf opened this issue Jun 13, 2024 · 0 comments
Labels
bug typescript Typescript related bugs

Comments

@wjhsf
Copy link
Contributor

wjhsf commented Jun 13, 2024

Description

The element returned by createElement is an HTML element with all of the @api-decorated properties from the provided component class. And we see, from usage, that it is very common for projects to use these additional props in their code. To improve the TypeScript developer experience in LWC v7, we updated the type signature to include the props in addition to the base HTMLElement interface. However, due to a limitation of TypeScript, it is not possible to detect which component props have been decorated. Consequently, we made the decision to include all component props on the return type, even though they don't all exist on the runtime object. This facilitates authoring TypeScript code when using the @api props, but it may cause confusion if users try to access the other props that don't actually exist.

Steps to Reproduce

// x/foo/foo.ts
import { api, LightningElement } from 'lwc';

export default class extends LightningElement {
  @api exposedProp = 'hello';
  privateProp = 'secret';
}

// app.ts
import { createElement } from 'lwc';
import Foo from 'x/foo';

const foo = createElement('x-foo', { is: Foo });
console.log(foo.exposedProp) // ok
console.log(foo.privateProp)
//              ^^^ should be a type error, but TypeScript thinks it's a string

Expected Results

The code should result in a type error: "Property 'privateProp' does not exist on type 'LightningHTMLElement'."

Actual Results

TypeScript thinks that foo.privateProp is a string, even though it doesn't actually exist at runtime.

Workaround

Users who want to have truly accurate types can provide an explicit generic parameter to createElement, and the returned type will include only the props exposed.

// These will have no additional properties, i.e. be just `HTMLElement`
const foo = createElement<object>('x-foo', { is: Foo });
const foo = createElement<LightningElement>('x-foo', { is: Foo });
// This will have only `exposedProp` available, *not* `privateProp`
const foo = createElement<{ exposedProp: string }>('x-foo', { is: Foo });
console.log(foo.exposedProp) // ok
console.log(foo.privateProp) // type error, as desired!

Users Affected

This bug only impacts projects written in TypeScript.

Version

  • LWC: 7.0.0
@nolanlawson nolanlawson added bug typescript Typescript related bugs labels Jun 13, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug typescript Typescript related bugs
Projects
None yet
Development

No branches or pull requests

2 participants