javascript - Typescript aruncă avertisment atunci când folosești obiecte JSON cu tipuri
Încerc să obțin proprietățile acestui obiect JSON într-un hook, folosind notația cu paranteze. Sunt sigur că funcționează, dar Typescript continuă să afișeze acel avertisment:
Proprietatea 'github' nu există pe tipul 'PropertyValues'
useI18n.ts
import { useRouter } from 'next/router'
import i18n from 'i18n/index.json'
type JSONRaw = typeof i18n
type Name = keyof JSONRaw
type Language = keyof JSONRaw[Name]
type Selection = JSONRaw[Name]
type Property = Pick<Selection, Language>
type PropertyValues = Property[Language]
export default function useI18n (name: Name) {
const { locale } = useRouter()
const JSONFile: JSONRaw = i18n
const wantedTextList = JSONFile[name]
const localeLanguage = locale as Language
const value = wantedTextList[localeLanguage]
return value as PropertyValues
}
JSON
{
"header": {
"es-ar": {
"text": "lorem ipsum 2."
},
"en-us": {
"text": "lorem ipsum."
}
},
"preferences": {
"es-ar": {
"text": "lorem ipsum 2"
},
"en-us": {
"text": "lorem ipsum"
}
},
"notavaible": {
"es-ar": {
"text": "lorem ipsum 2"
},
"en-us": {
"text": "lorem ipsum"
}
},
"postnav": {
"en-us": {
"github": "lorem ipsum 2",
"edit": " lorem ipsum"
},
"es-ar": {
"github": "lorem ipsum 2",
"edit": "lorem ipsum"
}
}
}
Iată utilizarea cârligului:
const { github, edit } = useI18n('postnav')
Mă aștept să obțin tipurile corecte și să le scalerez ușor
Răspuns #1
Trebuie să folosești un parametru generic astfel încât TS să poată deduce valoarea efectivă a literalului de șir pentru name la locul apelului.
Și din experimentul meu, trebuie de asemenea să adaugi manual o anotare a tipului de returnare pentru a ghida motorul TS, altfel acesta va deduce pur și simplu tipul de returnare ca fiind { text: string } | { github: string; edit: string }, ceea ce este corect dar nu suficient de specific.
Pus împreună, rezultatul este:
function useI18n<N extends Name>(name: N): JSONRaw[N][Language] {
const { locale } = useRouter()
const JSONFile: JSONRaw = i18n
const wantedTextList = JSONFile[name]
const localeLanguage = locale as Language
const value = wantedTextList[localeLanguage]
return value
}
Vezi-l în acțiune în TypeScript Playground.
