1

I have code like this In one file I have

interface NominativeCaseType {
    corn: string;
    buckwheat: string;
    rice: string;
    barley: string;
    wheat: string;
}

export const nominativeCase: NominativeCaseType = { // this is Називний Відмінок in Ukrainian language
    corn: 'Кукурудза',
    buckwheat: 'Гречка',
    rice: 'Рис',
    barley: 'Ячмінь',
    wheat: 'Пшениця',
}

in another file I have

import { nominativeCase } from '../../linguistics/categoriesNames';

export const MainScreen: React.FunctionComponent = () => {
    const [category, setCategory] = useState('corn');
    return (
        <article>
            {nominativeCase[category]}
        </article>
    )
}

and problem is that typescript dont allows me to use {nominativeCase[category]}. VsCode says

Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'NominativeCaseType'.
No index signature with a parameter of type 'string' was found on type 'NominativeCaseType'.ts(7053)

I tryied to google it, but still dont understand how what does it means and how to fix it. I even find solution like this Typescript error: TS7053 Element implicitly has an 'any' type And I change my code to

interface NominativeCaseType {
    [key: string]: string;
    corn: string;
    buckwheat: string;
    rice: string;
    barley: string;
    wheat: string;
}

But I still dont understand what does this error means and what [key: string]: string; means Help me please

1 Answers1

3

I believe the cleanest way to handle this is to specifically narrow the type of category to keyof NormativeCaseType. What that does is restrict the values to strings that are the property names.

const [category, setCategory] = useState<keyof NominativeCaseType>('corn');

The problem then is that you may need to narrow other incoming strings from callbacks or other untyped sources when you call setCategory.

const x: string = 'buckwheat';
setCategory(x as keyof NominativeCaseType);

Edit: [key: string]: string; is for defining a "catch-all" for properties that are not explicitly defined. You really don't want that here unless the object is really free-form and essentially "untyped" other than that the properties are all string values.

crashmstr
  • 28,043
  • 9
  • 61
  • 79
  • Thanks, but I mean how to solve current typescript error. You propose how to rewrite current logic, but there are even another logic. I just croppped code to show main. – Андрій Грушецький Apr 13 '21 at 13:59
  • @АндрійГрушецький `const [category, setCategory] = useState('corn');` should do the job. Please keep in mind, if code provided in your example is cropped, then it is on your side to make it right. – captain-yossarian from Ukraine Apr 13 '21 at 14:02
  • @АндрійГрушецький No, this is exactly how to solve the current typescript error and is not a "logic" change but a type change. I've added an edit to explain the `[key: string]: string;` and why it may not be what you want. – crashmstr Apr 13 '21 at 14:02