I wrote a small script to generate all possible values from i18n templates into a TypeScript file to type-check my usages of the i18n function. I am struggling to figure out how to get TypeScript to play nice with strings that do not take any parameters in.
This is my current translation function definition:
import { I18nStrings } from "./i18nStrings";
export type CheckedTFunction = <TKey extends keyof I18nStrings>(
key: TKey,
options: I18nStrings[TKey]
) => string;
My i18nStrings.ts file looks like this (Small snippet for brevity, the real file is about 2500 lines long):
type I18nArg = string | number;
export type I18nStrings = {
"common:abbreviatedMonths.april": never,
"common:abbreviatedMonths.august": never,
"common:buttons.filtersApplied": { "count": I18nArg, },
// ...
};
I incorrectly assumed that typing the args as never would allow TypeScript to be smart enough to figure out that the second parameter of the translation function should not be provided at all but it isn't the case: Linting (with tsc --build) my TypeScript files is raising errors for translation strings that don't take parameters, it expects the options parameter to be of any type.
Is what I am trying to do not possible? I am running TypeScript 4.2.3 at the moment.
Bonus points:
Linting does check that parameters are either strings or numbers with the right keys, but VS Code just reports the options argument as any. Is there something I can do to make VS Code smarter about this?
Edit: Based on @kaya3 's answer, this is what made it work:
export type CheckedTFunction = {
<K extends KeysWithOptions>(key: K, options: I18nStrings[K]): string;
<K extends KeysWithoutOptions>(key: K): string;
};