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'.
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];