vbenjs / vite-plugin-svg-icons

Vite Plugin for fast creating SVG sprites.
MIT License
816 stars 111 forks source link

Support TypeScript #22

Closed innocenzi closed 2 years ago

innocenzi commented 3 years ago

Hey,

So I'd like to have auto-completion on my icon names. A simple solution for that would be to generate a declaration file like icons.d.ts with a simple type:

declare type SvgIcon = 'users' | 'menu-alt' | 'home' | 'library' // ...

And using it in a component:

<script setup lang="ts">
import { computed } from 'vue'

const props = defineProps<{ name: SvgIcon }>() // <-- here
const symbolId = computed(() => `#icon:${props.name.includes(':') ? props.name : `:${props.name}`}`)
</script>

<template>
    <svg aria-hidden="true">
        <use :href="symbolId" />
    </svg>
</template>

This approach is taken from some plugin in the ecosystem, like antfu/vite-plugin-components which generates a components.d.ts.

I couldn't find how to use import ids from 'virtual:svg-icons-names' in a plugin to do this myself, so I see no other way than a first-party support.

gnuletik commented 2 years ago

Hi ! Thanks for implementing this !

However, I can't find a way to use it.

import ids from 'virtual:svg-icons-names'

typeof ids // type is string[]
typeof ids[number] // type is string

type IconName = typeof ids[number]

// logs: 'users', 'menu-alt'
console.log(ids)

// should throw a typescript error
const someIcon: IconName = 'icon-does-not-exist'

In order to let Typescript infer type from values, it seems that the export should be

export default ['users', 'menu-alt'] as const

cf https://steveholgado.com/typescript-types-from-arrays/

However, it doesn't seems defined as const https://github.com/vbenjs/vite-plugin-svg-icons/blob/d4d719ec1e465cd69b9153439f23d94aed94ab58/packages/core/src/index.ts#L152

Could you add as const to the export ?

Thanks!

gnuletik commented 2 years ago

I also tried to create a plugin that would generate a virtual import to export ['icon-name', ...] as const but I'm unable to use import ids from 'virtual:svg-icons-names' from a vite plugin as stated by @innocenzi.

For now, I'm manually handling the type of IconNames.

Thanks!

smiley-uriux commented 2 years ago

@anncwb Would you consider reopening this? Having the icon names available as a string array at runtime isn't super useful in most contexts, but having a typescript literal union of names would really improve the developer experience and would be a most welcome addition for anybody trying to create a generic "Icon" component that is smart enough to know what icons are available at compile time. I'm new to Vite so it's not obvious the preferred way to handle this, however with a little direction I'd be willing to work on a PR.