runem / lit-analyzer

Monorepository for tools that analyze lit-html templates
MIT License
318 stars 36 forks source link

Property binding produces 'no-incompatible-type-binding' error for 'default' types #154

Open patorpey opened 3 years ago

patorpey commented 3 years ago

When binding a particular class to a property on a subclass of LitElement, lit-plugin within VS Code produces an error on the binding of a class instance to that property in a template that a type of 'default' is not assignable to 'default'.

Material is a base class used as a data store.

pt-material is a subclass of LitElement that renders a view of data in Material instances and declares the property as such:

@property({attribute: false})
public material: Material;

Another subclass of LitElement binds instances of the Material class to pt-material elements.

public readonly items: Material[] = [];
public activeMaterial: Material | null;

// The items array is populated with Material instances and activeMaterial may
// be set to one of those instances as a result of user interaction elsewhere in this class.

public render(): TemplateResult {
    this.items.map(m => 
        html`<pt-material ?active=${this.activeMaterial === m} .material=${m}></pt-material>`);
}

The property name "material" in .material=${m} is underlined with the following error:

(property) .material: default
Type 'default' is not assignable to 'default' lit-plugin(no-incompatible-type-binding)(2304)

I have tried to satisfy the lit-plugin rule through more explicit Typescript typing and by adding type: Object to the @property decorator argument, but the error persists in this location. Elsewhere in my application I use similar bindings without the error, but haven't been able to identify what makes this occurrence unique, given the the error. I am uncertain what "default" indicates here. Typescript reports the type of m to be Material. The binding does function correctly at runtime, despite the error.

VS Code 1.52.1 Node.js: 12.14.1 Typescript: 4.1.2 lit-plugin: 1.2.1

patorpey commented 3 years ago

I am now seeing a similar error on a second property I've added to the pt-material custom elements mentioned in the original issue.

<pt-material ?active=${this.activeMaterial === m} .material=${m} .x=${x} .y=${y} .duration=${duration} .assembly=${(this.metadata as ProjectMetadata).assembly}></pt-material>

In this second instance, I received the following error:

(property) .duration: Nominal<number, "mstick"> | number
Type 'Nominal<number, "mstick"> | number' is not assignable to 'Nominal<number, "mstick"> | number'
lit-plugin(no-incompatible-type-binding)(2304)

In this second instance, the type of the property is a union with a generic utility type that is equivalent to number. (The branded type is used elsewhere, hence the union for the property.) Given the generic, this may be related to #163, though here the exact same type is said to be incompatible with itself, as in the original case. In the original, neither pt-material definition class nor the Material type is generic and I still haven't been able to determine what "default" is referring to. Other property bindings (primitive and complex) on pt-material do not generate an error and I'm not seeing this on other custom elements.

VS Code 1.57.0 Node.js: 14.16.0 Typescript: 4.3.2 lit-plugin: 1.2.1 lit-element: 2.4.0

MaKleSoft commented 10 months ago

@patorpey I know this issue is quite old, but I wonder if you're still experiencing this, or if you maybe found a fix or workaround? I'm still seeing the same issue in v1.4.0. The maddening thing is that it's really inconsistent (getting the error message in some places while not seeing it in others for the exact same type) and I haven't been able to reproduce the problem in a minimal project (so maybe it has something to do with the complexity/size of the project?). We rely on lit-plugin quite heavily at our company and this is really putting a damper on our productivity 😕

patorpey commented 10 months ago

@MaKleSoft Yes, I'm still experiencing this with version 1.4.0. After some refactoring and continued development (for purposes other than to satisfy lit-plugin), this is now only appearing in one file in one project, which includes the examples in my original issues above. I've not found a workaround. I just know that this file always is in an error state and have come to ignore it.

I've been hoping that this will someday be resolved by the release and adoption of the Lit team's own analyzer. It's been a while since they announced that and I imagine it will be a while longer before it gets integrated it into an equivalent Lit linter plugin.

VS Code 1.70.3 Node.js: 16.6.2 Typescript: 5.2.2 lit-plugin: 1.4.0

fengelniederhammer commented 7 months ago

I think I experienced the same bug:

    Type '{ displayName: string; content: DivisionOperatorResult<"dateRange", { dateRange: YearMonthDay | YearWeek | YearMonth | Year | null; count: number; }, "prevalence", "count", "total">[]; }[]' is not assignable to '{ displayName: string; content: DivisionOperatorResult<"dateRange", { dateRange: YearMonthDay | YearWeek | YearMonth | Year | null; count: number; }, "prevalence", "count", "total">[]; }[]'
    87:  .data=${data}
    no-incompatible-type-binding

From what I see, the types are equal (literally!). Could you please fix this?

As a workaround, I'm writing a data as { /* the concrete generic type */ }[], which works. But I don't want to type out my generic types explicitly every time I'm trying to pass them to a component.