TypeScript 如何在不出现 ESLint 警告的情况下读取两层深的 JSON 数据
示例 JSON
{
"files": {
"group1": {
"subgroup1": ["file1", "file2"]
},
"group2": {
"subgroup2": ["file3", "file4"],
"subgroup3": ["file5"]
}
}
}
我正在尝试创建一个函数,该函数可以根据组名和子组名给我一个随机文件
尝试 1
import data from "./data.json";
function getRandomImage(group: string, subgroup: string) {
const files = data.files[group][subgroup];
return files[Math.floor(Math.random() * files.length)];
}
上述代码给我这个错误
元素隐式具有 'any' 类型,因为无法使用类型为 'string' 的表达式来索引类型 '{ group1: { subgroup1: string[]; }; group2: { subgroup2: string[]; subgroup3: string[]; }; }'。在类型 '{ group1: { subgroup1: string[]; }; group2: { subgroup2: string[]; subgroup3: string[]; }; }' 上未找到参数类型为 'string' 的索引签名。
尝试 2
function getRandomImage(data: any, group: string, subgroup: string) {
const files = data.files[group][subgroup];
return files[Math.floor(Math.random() * files.length)];
}
我也尝试用任何类型传递数据,但那会报错
意外的 any 类型。请指定其他类型。
尝试 3
type groupType = keyof typeof data.files;
type subGroupType = keyof typeof data.files[groupType];
function getRandomImage(group: groupType, subgroup: subGroupType) {
const files = data.files[group][subgroup];
return files[Math.floor(Math.random() * files.length)];
}
那给我错误
属性 'length' 在类型 'never' 上不存在。
我对 TypeScript 非常陌生(来自 Python),所以这一直很麻烦……请帮帮我。
答案#1
如果你想要用于手动使用的已键入函数(即它会建议可用的参数),请根据第一个参数推断可能的第二个参数:
// imported json is const type
const json = {
"files": {
"group1": {
"subgroup1": ["file1", "file2"]
},
"group2": {
"subgroup2": ["file3", "file4"],
"subgroup3": ["file5"]
}
}
} as const;
type jsonT = typeof json.files;
function getRandomImage<
K1 extends keyof jsonT,
K2 extends keyof jsonT[K1]
>(group: K1, subgroup: K2) {
const files = json.files[group][subgroup] as string[];
return files[Math.floor(Math.random() * files.length)];
}
// won't allow improper args
getRandomImage('group1', 'subgroup1')
如果你不在乎键是否是合格的键,将类型扩展为字符串:
// widen the type to {"a":{"b":["c"]}} with any strings
const filesRecord: Record<string, Record<string, string[]>> = json.files;
// or {[p: string]: {[p2: string]: string[]}} which means same
function getRandomImage(group: string, subgroup: string) {
const files = data.files[group][subgroup];
return files[Math.floor(Math.random() * files.length)];
}
