tailwindlabs / heroicons

A set of free MIT-licensed high-quality SVG icons for UI development.
https://heroicons.com
MIT License
21.03k stars 1.27k forks source link

Type mismatch when used as Vue dynamic component #963

Closed AndreKR closed 1 year ago

AndreKR commented 1 year ago

In the (paid) Tailwind UI sidebar layout the icons are used as Vue dynamic components like this:

<template>
  <a v-for="item in navigation">
    <div><component :is="item.icon" /> {{ item.name }}</div>
  </a>
</template>

<script setup lang="ts">
  import { HomeIcon } from '@heroicons/vue/24/outline';

  let navigation = [
    {icon: HomeIcon, name: 'Home'}
  ];
</script>

In PhpStorm (which I believe just passes through the TypeScript errors) the tag <component :is="item.icon" /> causes an inspection error:

Type FunctionalComponent<HTMLAttributes & VNodeProps> is not assignable to type string | ComponentDefinition Type FunctionalComponent<HTMLAttributes & VNodeProps> is not assignable to type ComponentConstructor Type FunctionalComponent<HTMLAttributes & VNodeProps> is not assignable to type ComponentDefinition

Note that the Type FunctionalComponent<HTMLAttributes & VNodeProps> was inferred automatically, I did not specify an explicit type. (I don't know what's the type of HomeIcon is supposed to be.)

reinink commented 1 year ago

Hey! Can you share a minimal reproduction of this as a repo? It's really hard to reproduce this issue without one. Thanks!

AndreKR commented 1 year ago

https://github.com/AndreKR/heroicons-issue-963

To reproduce:

image

Now, the way I set up the repro, it can also run tsc. To do so, you can run yarn run check. However, the error does not appear then, so it might just as well be an error with PhpStorms type inferrence. I don't know enough about TypeScript to analyze what those types mean exactly.

little3201 commented 1 year ago

same question for me

thecrypticace commented 1 year ago

This is a problem with PHPStorm's Vue plugin. It ships type definitions for HTML elements and they are referencing types that don't exist (or are outdated).

I discovered this by peering into the PHPStorm app bundle, locating the Vue JS plugin, and extracting the types from it (the plugin is a .jar which is just a specially-treated zip file). The types for <component> appear to be nearly identical in Vue 2 and Vue 3 according to PHPStorm.

Here's where I looked (at least on macOS) — you'll see here that I extracted the contents of the .jar file to make the screenshot easier to follow:

Screenshot 2023-05-11 at 16 16 39

Here's screenshots for the v3 (and v2 for reference) types:

Screenshot 2023-05-11 at 16 15 12 Screenshot 2023-05-11 at 16 15 05

However Vue 3 does not export a type called ComponentDefinition:

Screenshot 2023-05-11 at 16 23 55

Vue 3 technically did, at one time, have a ComponentConstructor<This> type. However, this type was only internal and not exported and it disappeared in 2019-ish.

Now, it could be that ComponentDefinition is a PHPStorm-specific thing. But, in that case, the definition is incorrect as even a component created with defineComponent fails (and the component does work as expected):

Screenshot 2023-05-11 at 16 32 49

All in all, this is a PHPStorm issue with its own internal Vue types. Hope that helps. ✨