2

I would like to convert my existing Javascript CustomElements/WebComponents (made with Lit v1 and ported to v2) to TypeScript.

Example:

export class MyElement extends LitElement {
  ...
  @property({type: String})
  name = 'World';
  ...
}

... or another one: https://github.com/lit/lit-element-starter-ts/blob/main/src/my-element.ts#L37

How can I define a property as an array of my custom typescript classes?

E.g. something like this:

export class MyElement extends LitElement {
  ...
  @property({type: Array<MyCustomClass>})
  customClassArray = [];
  // or: customClassArray = [new MyCustomClass("foo")]; 
  ...
}
StephanB
  • 315
  • 2
  • 17
  • That's a runtime type declaration. Typescript types are compile-time only. More info here: https://lit.dev/docs/components/properties/#conversion-type – Ege Özcan Jan 06 '22 at 12:02

2 Answers2

1

Lit's @property decorator is all about setting up a reactive property AND reflecting the attribute to the value (and vice versa if you turn on reflect: true). However, this conversion for HTML elements is tricky on non-string values, e.g. numbers shall be parsed to an actual number, for a boolean value the existence of the attribute means true etc.

That is why Lit needs type, to be able to choose the correct converter for the attribute value. Think of it as a type-hint or a converter-type regarding attribute/value conversion. Take a look at Lit's default converter.

Your actual types should be defined in TypeScript.

export class YourElement extends LitElement {
  @property({ type: Array })
  customClassArray = new Array<YourCustomClass>();
  // or: customClassArray = [new YourCustomClass()];
}
arshia11d
  • 26
  • 4
  • Thank you - I see you edited L2. I thought Lit would be capable to interpret custom types directly within the property decorator. – StephanB Jan 06 '22 at 13:19
  • I'm having trouble with this as well. In all questions I'm missing the HTML side. Are you binding this via ``? – EluciusFTW Jul 06 '23 at 13:34
1

I think I have found a solution by myself, quite similiar to @arshia11d answer.

import { MyCustomClass } from './MyCustomClass';    

export class MyElement extends LitElement {
      @property({ type: Array }) //Array<MyCustomClass> throws ts(2303) error
      annotations: MyCustomClass[] = [];
    }

Type definition:

export interface IMyCustomClass {
  label: string;
}

export class MyCustomClass implements IMyCustomClass {
  label: string;

  constructor(
    _label: string
  ) {
    this.label = _label;
  }
}
StephanB
  • 315
  • 2
  • 17