2

So i wanted to have all the icon names in the autocomplete from the react native icons module. Unfortunately the typings they provide do not include the names as an union type.

So my question is, importing an object (that typescript recognizes, with all its keys), how can I get all the keys as a union type.

Currently this is the only thing i came up with

import React from 'react';
import { MaterialCommunityIcons as Icon } from '@expo/vector-icons';
import { IconProps } from '@types/react-native-vector-icons/Icon'
import glyphmap from 'react-native-vector-icons/glyphmaps/MaterialCommunityIcons.json'

// create a type where I can do keyof
type MyMap<T> = {
    [ P in keyof T ]: number
};

// unnecessary? function that maps any input
// to MyMap. 
function something<T>(input: T) : MyMap<T> {
    return (input as any) as MyMap<T>
}

const result = something(glyphmap);

// finally I get all keys from glyphmap as union of string literals    
type MapKeys = keyof MyMap<typeof result>

interface Props extends IconProps {
    name: MapKeys
}

const MyIcon = (props: Props) => (
    <Icon {...props} />
)

// using here the name prop gives me all the keys as autocomplete
const Test = props => (
    <MyIcon name="access-point" />
)

So as you can see, I couldn´t find any other way, how I could convert the glyphmap from a json file to something like this, without passing it through a senseless function

type MyMap<T> = {
    [ P in keyof T ]: number
};

So one more time the question more precise:

How do I convert an untyped object into MyMap without passing it through a function

1 Answer 1

2

UPDATE

So after looking into import types (great thanks to Madara Uchiha) the whole thing can be transformed into one line of code... :D

type Glyphmap = typeof import('somemodule/.../file.json')

ORIGINAL

Oh, as soon as I sent the question, I looked over the code again and found that the typeof result could be also directly typeof glyphmap. So I tried and it worked perfectly. So no need of this useless function.

import React from 'react';
import { MaterialCommunityIcons as Icon } from '@expo/vector-icons';
import { IconProps } from '@types/react-native-vector-icons/Icon'
import glyphmap from 'react-native-vector-icons/glyphmaps/MaterialCommunityIcons.json'

type MyMap<T> = {
    [ P in keyof T ]: number
};

// spread keys after converting glyphmap into MyMap
type MapKeys = keyof MyMap<typeof glyphmap>

interface Props extends IconProps {
    name: MapKeys
}

const MyIcon = (props: Props) => (
    <Icon {...props} />
)

const Test = props => (
    <MyIcon name="account" />
)
Sign up to request clarification or add additional context in comments.

3 Comments

You can shorten it even further to type MapKeys = keyof typeof glyphmap. And you can further reduce the resulting bundle if you used import types
Oh that sounds even more interesting. If you could provide an answer with some explanation I would gladly support your answer more, if it reduces it even more!
Nevemind, I really could simplify this to just one line. wow. :) thanks a lot.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.