To start, it is essential to extract permissible values from the translations
object. To achieve this, the translations
object needs to be made immutable.
const translations = {
msg_hello: 'Hello',
msg_bye: 'Bye'
} as const;
For better readability, a helper type can be created:
type Translations = typeof translations;
Utilizing template literals, it becomes possible to deduce the string following the underscore character _
:
type GetSuffix<T> = keyof T extends `msg_${infer Suffix}` ? Suffix : never;
type Test = GetSuffix<Translations> // "hello" | "bye"
Subsequently, the restriction can be applied:
const generateTranslation = <
Key extends GetSuffix<Translations>
>(partialKey: Key): `msg_${Key}` => `msg_${partialKey}`
It should be noted that partialKey
has been inferred using GetSuffix<Translations>
to enable the application of an explicit return type, msg_${Key}
.
Complete example:
const translations = {
msg_hello: 'Hello',
msg_bye: 'Bye'
} as const;
type Translations = typeof translations;
type GetSuffix<T> = keyof T extends `msg_${infer Suffix}` ? Suffix : never
type Test = GetSuffix<Translations> // "hello" | "bye"
const generateTranslation = <
Key extends GetSuffix<Translations>
>(partialKey: Key): `msg_${Key}` => `msg_${partialKey}`
const result = generateTranslation('hello'); // good ---> "msg_hello"
generateTranslation('no'); // bad
Playground