Home > OS >  Modify prop value before TypeScript check
Modify prop value before TypeScript check

Time:10-05

This is the object I've got:

const translations = {
    msg_hello: 'Hello',
    msg_bye: 'Bye'
}

Also I have a function that looks like this:

const generateTranslation = (partialKey: string): keyof typeof translations {
    return `msg_${partialKey}`;
}

is there a way to check if the generated translation key will be valid? For example:

generateTranslation('hello'); // good
generateTranslation('no'); // bad

CodePudding user response:

I don't think there is an automatic way to do this, for dynamic strings like that where keyof won't retrieve them. But you could manually create a type that is a union of the valid values, and require that the partialKey argument be of that type:

const translations = {
    msg_hello: 'Hello',
    msg_bye: 'Bye'
};

type validPartialKeys = 'hello' | 'bye';

const generateTranslation = function (partialKey: validPartialKeys): keyof typeof translations {
    return `msg_${partialKey}`;
}

generateTranslation('hello'); // good
generateTranslation('no'); // bad

CodePudding user response:

First of all, you need extract allowed values from translations. In order to do that, you need to make translations immutable.

const translations = {
    msg_hello: 'Hello',
    msg_bye: 'Bye'
} as const;

Then, for the sake of readability, you can create helper type:

type Translations = typeof translations;

Thanks to template literals, you can infer the string which goes after underscore _:

type GetSuffix<T> = keyof T extends `msg_${infer Suffix}` ? Suffix : never;

type Test = GetSuffix<Translations> // "hello" | "bye"


Now, you can apply the restiction:


const generateTranslation = <
    Key extends GetSuffix<Translations>
>(partialKey: Key): `msg_${Key}` => `msg_${partialKey}`

Be aware that I have infered partialKey with help of GetSuffix<Translations> which helped me to apply explicit return type msg_${Key}.

WHole 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

  • Related