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

Problem with custom directives (no-incompatible-type-binding) #207

Open
WickyNilliams opened this issue Oct 27, 2021 · 2 comments · May be fixed by #364
Open

Problem with custom directives (no-incompatible-type-binding) #207

WickyNilliams opened this issue Oct 27, 2021 · 2 comments · May be fixed by #364

Comments

@WickyNilliams
Copy link

I have been trying to write a simple custom directive which simplifies some use-cases for ifDefined:

// instead of
html`<input pattern=${ifDefined(isNumber ? "[0-9]*" : undefined)} />`

// i would like to do this
html`<input pattern=${cond(isNumber, "[0-9]*")} />`

Cribbing from ifDefined, I came up with this directive:

const cond = <T>(condition: boolean, value: T) => (condition ? value : nothing)

This directive works just fine at runtime, but the vscode plugin complains:

Type 'Symbol(undefined) | "[0-9]*"' is not assignable to 'string'

So I also tried creating a directive as recommended in the lit docs:

class ConditionalDirective extends Directive {
  constructor(partInfo: PartInfo) {
    super(partInfo)
    if (partInfo.type !== PartType.ATTRIBUTE) {
      throw new Error("The `cond` directive must be on attributes")
    }
  }

  render(condition: boolean, value: string) {
    return condition ? value : nothing
  }
}

// Create the directive function
cond = directive(ConditionalDirective)

But now i get a different error:

You are binding a non-primitive type 'DirectiveResult<{ prototype: any; new(partInfo: ChildPartInfo | AttributePartInfo | ElementPartInfo) => ConditionalDirective; }>'. 
This could result in binding the string "[object Object]". Use '.' binding instead?

Again, the directive itself works fine at runtime...

I tried following the advice in the error message but then I get a different error again:

Type 'DirectiveResult<{ prototype: any; new(partInfo: ChildPartInfo | AttributePartInfo | ElementPartInfo) => ConditionalDirective; }>' is not assignable to 'string'

Am I doing something wrong here, or is this a bug with lit-analyzer?

@WickyNilliams
Copy link
Author

WickyNilliams commented Oct 27, 2021

Interestingly, the complaints go away if i remove the generics from my basic function directive and make value be any.

const cond = (condition: boolean, value: any) => (condition ? value : nothing)

Though I don't really want to lose typing. And still the problem persists when extending Directive regardless of how i type the render function

Edit: ignore this comment. Of course this works, I'm opting out of type checking with any.

@WickyNilliams WickyNilliams changed the title Problem with custom directives Problem with custom directives (no-incompatible-type-binding) Oct 28, 2021
@tpluscode
Copy link

I'm having the same problem and I actually would expect the attribute binding to work all the same. In my case, I have a directive which does translation <mwc-tab label="${translate(item)}">. The result of that directive is a string. Lit is perfectly content updating the attribute from the directive result.

For now it appears that I have to bind translate(item) as any...

SegaraRai added a commit to SegaraRai/lit-analyzer that referenced this issue Jul 27, 2024
@SegaraRai SegaraRai linked a pull request Jul 27, 2024 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants