Home > Software design >  TS keyof 2d array
TS keyof 2d array

Time:07-08

I have a huge 2D array that contains/represents translations, that could look like this (just as an example)

const translations = {
    'login': {
        'e-mail': 'E-Mail',
        'username': 'Username',
        'forgot-password': 'Forgot your password?'
    },
    'dashboard': {
        'hello {x}': 'Hello {x] how is your day?',
        'go-to-other-page': 'Go to page...'
    }
}

I then made an Interface with all translation categories and their strings

interface AllTranslations {
    login: {} // contains all messages,
    dashboard: {} // contains all messages
}

and I made a function that returns the correct translation.

type TranslationCategory<T = keyof AllTranslations> = keyof AllTranslations[T];

const translate = <T extends keyof AllTranslations>(key: T, message: TranslationCategory<T>, params: {[key: string]: string|number} = {} ): string => {
    const m = translations[key][message] ?? message;
    // do something with the message, format / replace params
    return m as string;
}

So I can use it like

translate('login', 'username');
translate('dashboard', 'hello {x}', {x: 'User'});

and my categories as well as the string will be autocompleted. Everything works so far but for whatever reason the line

type TranslationCategory<T = keyof AllTranslations> = keyof AllTranslations[T];

has an error TS2536: Type 'T' cannot be used to index type 'AllTranslations'. enter image description here

What can I do in order to prevent this error except including a //@ts-ignore above it. What is the correct way to use keyof with a 2d array correctly with the ability to autocomplete code correctly?

A playground is here and autocomplete is working perfectly, I just don't know why there is the error.

CodePudding user response:

The issue is with:

type TranslationCategory<T = keyof AllTranslations> = keyof AllTranslations[T];

What happens is that T is defaulted to a union of keyof AllTranslations ('login' | 'dashboard'), whereas you want T to be one of keyof AllTranslations.

You should use extend instead of an assigning operator:

type TranslationCategory<T extends keyof AllTranslations> = keyof AllTranslations[T];
  • Related