expo / vector-icons

https://icons.expo.fyi
MIT License
650 stars 113 forks source link

Icon names types are not exported #153

Closed VictorAssis closed 3 years ago

VictorAssis commented 3 years ago

fca0e34f827bc172012a0dd58a384d542d7dee67 turned possible to autocomplete the icons names, but is not possible to reference in a wrapper component (without copy and paste the names manually) because the names are not a separated type.

For example i had this component working in a older version of @expo/vector-icons:

import { MaterialIcons } from '@expo/vector-icons';

interface Props {
  icon: string,
  label: string,
  color: string
}

const CustomDrawerItem = ({ icon, label, color }: Props) => (
  <View>
    <MaterialIcons
      name={icon}
      color={color}
    />
    <Text>{label}</Text>
  </View>
}

In the current version, Typescript present the error Type 'string' is not assignable to type '"label" | "style" | (...).

Is it possible to export the names in a separate type for import as below?

import { MaterialIcons, MaterialIconsNames } from '@expo/vector-icons';

interface Props {
  icon: MaterialIconsNames,
  label: string,
  color: string
}

const CustomDrawerItem = ({ icon, label, color }: Props) => (
  <View>
    <MaterialIcons
      name={icon}
      color={color}
    />
    <Text>{label}</Text>
  </View>
}

Or is there another solution?

de1ay commented 3 years ago

Try this

import { MaterialIcons } from '@expo/vector-icons';

type Props = {
  materialIconName: keyof typeof MaterialIcons.glyphMap;
}

Result

Screenshot 2020-12-31 004823

VictorAssis commented 3 years ago

This works fine! Thanks!

brentvatne commented 3 years ago

the solution suggested by @de1ay is a common way to do this kind of thing. if someone would like to propose an alternative approach to exposing the icon name prop along with some justification on why it's worth adding the extra surface area to api and documentation, please do!

soullivaneuh commented 3 years ago

@brentvatne The approach looks good too me. It should be added on top of the documentation, this is a very useful trick that deserve a better place than a github issue comment. :wink:

brentvatne commented 3 years ago

feel free to send a pr for it - that said, extracting types of props on a component is a pretty common thing to do when using react libraries with typescript, so you can use this common pattern:

type MaterialIconName = React.ComponentProps<typeof MaterialIcons>['name'];
const iconName: MaterialIconName =  '3d-rotation'

example of it in action:

Screen Shot 2021-02-27 at 12 24 32 PM
OlammieAO commented 9 months ago

@JereLima , Nice solution you have provided and that's a good one. If I may understand, does it mean that we can use the "MyIcon" component to display any @expo/vector-icons icon on the main display screen. For example, say I want to use Entypo icon which is below:

How am I going to use the MyIcon component in this manner so that I can be able to pass any Icon type like Fontisto, Ionicons, FontAwesome ? e.g

import MyIcon from './MyIcon'

the question is "how would i pass in the Icon type i want to use if Entypo, MaterialIcons, FontAwesome e.t.c...." to this component in the screen using this component?

I love your solution though.

Thank you

Valli- commented 5 months ago

That solution can slow down the intellisense, https://github.com/microsoft/TypeScript/wiki/Performance#preferring-base-types-over-unions. I was testing it out and took quite big performance issue after a while.