You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TypeScript异步加载JSON:如何避免代码重复并获取正确类型形状?

TypeScript异步加载JSON文件获取正确类型的优化方案

问题场景

当通过异步函数动态加载不同语言的JSON文件时,所有JSON结构完全一致,但直接通过Awaited<ReturnType<typeof loadMessages>>推导类型时,foo字段会被解析为any:

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
});

推导结果:

type AppMessages = {
    foo: any;
}

之前的解决方案虽能得到正确类型,但存在大量重复代码,现需要一种无需手动定义AppMessages、无代码冗余的方案。

优化方案

方案1:基于默认JSON文件提取基准类型

直接从默认语言的JSON文件中提取类型,作为所有动态加载JSON的类型基准,无需重复定义结构:

// 导入默认语言的JSON,仅用于提取类型(编译时不会引入冗余代码)
import enFoo from '../../messages/en/foo.json';
type FooMessages = typeof enFoo;

export type Locale = "en" | "fr" | "es";

// 明确返回值类型,对齐基准类型
export const loadMessages = async (locale: Locale): Promise<{ foo: FooMessages }> => ({
  foo: (await import(`../../messages/${locale}/foo.json`)).default
});

// 自动推导正确的AppMessages类型,无需手动编写结构
export type AppMessages = Awaited<ReturnType<typeof loadMessages>>;

方案2:复用默认加载函数提取类型

利用默认语言的加载函数同时实现逻辑复用和类型提取,进一步简化代码:

export type Locale = "en" | "fr" | "es";

// 默认语言加载函数,既用于逻辑实现,也用于提取类型
const loadEnMessages = async () => ({
  foo: (await import('../../messages/en/foo.json')).default
});

// 从默认加载函数提取基准类型
type BaseMessages = Awaited<ReturnType<typeof loadEnMessages>>;

// 通用加载函数,直接复用基准类型
export const loadMessages = async (locale: Locale): Promise<BaseMessages> => {
  if (locale === 'en') {
    return loadEnMessages();
  }
  return {
    foo: (await import(`../../messages/${locale}/foo.json`)).default
  };
};

// AppMessages直接复用基准类型,无需额外推导
export type AppMessages = BaseMessages;

方案说明

两种方案均利用TypeScript的类型推导能力,通过typeof、ReturnType、Awaited等工具类型从已有资源(JSON文件或加载函数)中提取类型,确保动态加载的JSON类型与基准类型一致,同时完全避免了代码重复和手动定义类型结构的繁琐。

内容的提问来源于stack exchange,提问作者Yanick Rochon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 22:53:16