好的,我感谢到目前为止的 comments ,让我更具体地重新定义这个问题.
我有以下设置:
type AbstractIntlMessages = {
[id: string]: AbstractIntlMessages | string;
};
interface Translations<Locales extends string, Messages extends AbstractIntlMessages = AbstractIntlMessages> {
Messages: Record<Locales, () => Promise<{ default: Messages }>>;
}
async function combineTranslations<
Locales extends string,
Messages extends AbstractIntlMessages = AbstractIntlMessages
>(locale: Locales, definitions: Array<Translations<Locales>>): Promise<Messages> {
const imported = await Promise.all(definitions.map((definition) => definition.Messages[locale]()));
const translations = imported.map((t) => t.default);
return Object.assign({}, ...translations);
}
const SiteTranslations = {
Messages: {
en_US: () => Promise.resolve({ default: { Site: { title: 'My Site' } } }),
es_US: () => Promise.resolve({ default: { Site: { title: 'Mi Sitio' } } }),
}
};
const AuthFeatureTranslations = {
Messages: {
en_US: () => Promise.resolve({ default: { Auth: { title: 'My Auth' } } }),
es_US: () => Promise.resolve({ default: { Auth: { title: 'Mi Autentico' } } }),
}
};
const locales = ['en_US', 'es_US'] as const;
type Locales = (typeof locales)[number];
async function i18n(locale: Locales) {
const messages = await combineTranslations(locale, [
SiteTranslations,
AuthFeatureTranslations
]);
console.log(messages)
}
i18n('en_US')
运行combineTranslations
后,messages
的类型是AbstractIntlMessages
.
How do I structure the types of 100 such that the type of 101 is:
{
Site: {
title: string;
};
Auth: {
title: string;
};
}
我正在使用next-intl
,它使用messages
的类型来驱动开发期间的自动完成和类型验证.目前这不起作用,因为messages
的类型是AbstractIntlMessages
.
我还要注意,messages
的属性是否只读并不重要.此外,messages
的叶属性可以是string
,也可以是翻译中的实际字符串值.
以下是TSplayground 的链接,代码为:https://tsplay.dev/w8qj4N