I'm currently working on a web project which heavily utilizes internationalization (i18n) and I have a hard time figuring out how to make sure all languages share exact same keys.
Here's a simple example of src/lang/en.ts
file:
export default {
title: "My Website Project",
description: "This is an example of a file which contains phrases and their keys",
hello: "Hello!",
};
and here's a simple example of src/lang/id.ts
file:
export default {
title: "Proyek Website Saya",
description: "Ini adalah contoh dari sebuah file yang mengandung beberapa frasa beserta kata kuncinya",
hello: "Halo!",
};
Now, I want TypeScript to make sure those files have same keys (not more, not less). So if I put cat
property into src/lang/id.ts
, then:
export default {
title: "Proyek Website Saya",
description: "Ini adalah contoh dari sebuah file yang mengandung beberapa frasa beserta kata kuncinya",
hello: "Halo!",
cat: "Kucing", // <-- this must be error because "cat" doesn't exist in en.ts file!
};
But I can't build an interface like this
export default interface LanguageStruct {
title: string,
description: string,
hello: string,
};
Because there's hundreds of phrases for each language in the real project and writing those keys one-by-one would be both time consuming and exhausting. I wonder if there's a trick to do with TypeScript for that problem, or at least there's some kind of automation to do that job.
CodePudding user response:
Use keyof typeof someObject
to construct a type from the keys of an object (e.g. the first language strings). Then restrict your other object (the other languages) to have that type as key, and string as value using Record
. So the type you're looking for is Record<keyof typeof someObject, string>
. Example:
const en = {
title: "My Website Project",
description: "This is an example of a file which contains phrases and their keys",
hello: "Hello!",
};
const de: Record<keyof typeof en, string> = {
title: "Proyek Website Saya",
description: "Ini adalah contoh dari sebuah file yang mengandung beberapa frasa beserta kata kuncinya",
hello: "Halo!",
cat: "Kucing", // this is highlighted as an error
};
See working example here.