typescript hur man läser json-data 2 nivåer djupt utan eslint-varningar
Exempel JSON
{
"files": {
"group1": {
"subgroup1": ["file1", "file2"]
},
"group2": {
"subgroup2": ["file3", "file4"],
"subgroup3": ["file5"]
}
}
}
Jag försöker bygga en funktion som ger mig en slumpmässig fil, givet grupp- och undergruppsnamn
Försök 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)];
}
Koden ovan ger mig detta fel
Elementet har implicit typen 'any' eftersom ett uttryck av typen 'string' inte kan användas för att indexera typen '{ group1: { subgroup1: string[]; }; group2: { subgroup2: string[]; subgroup3: string[]; }; }'. Ingen indexsignatur med en parameter av typen 'string' hittades på typen '{ group1: { subgroup1: string[]; }; group2: { subgroup2: string[]; subgroup3: string[]; }; }'.
Försök 2
function getRandomImage(data: any, group: string, subgroup: string) {
const files = data.files[group][subgroup];
return files[Math.floor(Math.random() * files.length)];
}
jag försökte också skicka data med vilken typ som helst, men det ger ett fel
Oväntad any. Specificera en annan typ.
Försök 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)];
}
det ger mig ett fel
Egenskapen 'length' finns inte på typen 'never'.
Jag är väldigt ny på TypeScript (kommer från Python), så det här har varit ett stort besvär.. snälla hjälp mig.
Svar #1
Om du vill ha en typad funktion för manuell användning (dvs. den föreslår tillgängliga argument), härled möjligen det andra argumentet från det första argumentet:
// 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')
Om du inte bryr dig om att nycklarna är riktiga nycklar, vidga typerna till sträng:
// 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)];
}
