From the following example:
export type AppMessages = Awaited<ReturnType<typeof loadMessages>>;
export type Locale = "en" | "fr" | "es";
export const loadMessages = async (locale: Locale) => ({
foo: locale === 'en'
? (await import('../../messages/en/foo.json')).default
: (await import(`../../messages/${locale}/foo.json`)).default
});
All JSON files have the same shape, however the AppMessages type is resolved as
type AppMessages = {
foo: any;
}
I thought about this solution:
export type AppMessages = Awaited<ReturnType<typeof loadDefaultMessages>>;
export type Locale = "en" | "fr" | "es";
const loadDefaultMessages = async () => ({
foo: (await import("../../messages/en/foo.json")).default,
});
const loadLocaleMessages = async (locale: Locale): Promise<AppMessages> => ({
foo: (await import(`../../messages/${locale}/foo.json`)).default,
});
export const loadMessages = async (locale: AppLanguages) =>
locale === "en"
? await loadDefaultMessages()
: await loadLocaleMessages(locale);
Which has the AppMessages type correctly shaped, however this solution will lead to a lot of repetitions and potential code duplications.
Is there a better solution yielding the same result, that is having AppMessages be shaped according to the JSON data files. Manually setting the AppMessages type is not an option.
Only you (can) know that all the
foo.jsonfiles in any of those directories will (or at least should) have the exact same shape as the one in the /en/ directory. So you must tell TypeScript:then