I'm trying to build a translation service. The function that is used to translate tags should provide type checking on possible tags, but also on the replacement object based on the given tag.
I have a tag list object that describes the possible tags and a list of placeholders that should be present inside the translated string.
export const TagList = {
username_not_found: ['username']
};
The key in this case is the tag name that a dictionary should implement. The value is a list of placeholders that should be present in the translated string.
A dictionary looks somewhat like this:
// Note: The type declaration of keys don't work this way (key should be number or string). Not sure how I should implement this...
const en: {[name: keyof (typeof TagList)]: string} = {
"username_not_found": "The user {username} does not exist"
}
The method used to translate tags with works like this:
this.trans("username_not_found", {username: "someone@example.com"});
What I'm trying to achieve is type checking (autocompletion) in my IDE for the placeholder object to enforce that all placeholders are configured.
For example:
// This is wrong: "username" placeholder is not specified.
this.trans("username_not_found", {});
// This is also wrong: "foobar" is a non-existing placeholder.
this.trans("username_not_found", {foobar: "42"});
// This is good:
this.trans("username_not_found", {username: "someone@example.com"});
Currently I'm using keyof (typeof TagList)
as the argument type for tagName
. I'm not sure if this is the correct way of doing this, but it works. I'm now looking for a way to infer the object stucture of the second argument based on the value given in the first argument.
I'm trying to avoid having to maintain multiple lists of possible tags (e.g. having to declare them in both an interface and an object at the same time).
Thanks in advance!