2
votes

I have an object that I need to type, but am unsure how to do this. The following is the error I am seeing and my code is below.

Element implicitly has an 'any' type because type '{ LIV: string; MAN: string; LDN: string; }' has no index signature. [7017]

type Props = {
    city: string;
    cityMap: {
        LIV: string;
        MAN: string;
        LDN: string;
    };
};

const Cities = ({ city }: Props) => {
    const cityMap = {
        LIV: 'Liverpool',
        MAN: 'Manchester',
        LDN: 'London'
    };

    const city = cityMap[city];
    return <>{city}</>;
};
1

1 Answers

1
votes

With noImplictAny typescript will not let you index into objects with arbitrary strings (as this is not really type safe and the result of such an index operation would implicitly be any)

There are several possible solutions.

Change the type of city to be keyof Props['currencyMap']

type Props = {
    city: keyof Props['currencyMap'];
    currencyMap: {
        LIV: string;
        MAN: string;
        LDN: string;
    };
};

const Cities = ({ city }: Props) => {
    const cityMap = {
        LIV: 'Liverpool',
        MAN: 'Manchester',
        LDN: 'London'
    };

    const cityName = cityMap[city];
};.

Or use a type assertion to tell the compiler you are sure city will be an apropriate key:

const Cities = ({ city }: Props) => {
    const cityMap = {
        LIV: 'Liverpool',
        MAN: 'Manchester',
        LDN: 'London'
    };

    const cityName = cityMap[city as keyof Props['currencyMap']];
};

Or you can use a check to ensure city is an expected key with a custom type guard:

const Cities = ({ city }: Props) => {
    const cityMap = {
        LIV: 'Liverpool',
        MAN: 'Manchester',
        LDN: 'London'
    };
    const isCity = (c: string): c is keyof Props['currencyMap'] => c in cityMap; 
    if (isCity(city)) {
        cityMap[city];
    }else { /* What now ? error ? */ }
};