In my current project, I am working on a function that takes two generic parameters: "index" which is a string and "language" which can also be any string. The goal of the function is to validate if the given language is supported and then return a formatted string in the form of
${index or T}_${one of SupportedLanguages}
.
So far, I have managed to ensure that the function works correctly, for example:
const res = getIndexWithPrefixByLanguage('haha') // returns type 'haha'
const res2 = getIndexWithPrefixByLanguage('haha', 'ja') // returns type 'haha_ja'
The issue I am facing now is narrowing down the second parameter U to one of the supported languages. It seems like the problem lies within the return type signature.
Below is the full code snippet:
export type SupportedLanguage = 'ko' | 'ja' | 'zh'
export const SUPPORTED_LANGUAGES = ['ko', 'ja', 'zh']
interface IndexMap<T extends string> {
ko: T
ja: `${T}_ja`
zh: `${T}_zh`
}
export function getIndexWithPrefixByLanguage<
T extends string,
U extends string,
>(index: T, language?: U): IndexMap<T>[U extends SupportedLanguage ? U : 'ko'] {
if (!validateLanguage(language)) {
return index
}
console.log(language)
const map: IndexMap<T> = {
ko: index,
ja: `${index}_ja`,
zh: `${index}_zh`,
}
// how to narrow down to one of Supported Language type?
return map[language]
}
export function validateLanguage(
language?: any,
): language is SupportedLanguage {
return !!language && SUPPORTED_LANGUAGES.includes(language.toLowerCase())
}
When trying to compile the code, I encounter the following error:
Type 'IndexMap<T>[U & "ko"] | IndexMap<T>[U & "ja"] | IndexMap<T>[U & "zh"]' is not assignable to type 'IndexMap<T>[U extends SupportedLanguage ? U : "ko"]'.
Type 'IndexMap<T>[U & "ja"]' is not assignable to type 'IndexMap<T>[U extends SupportedLanguage ? U : "ko"]'.
Type 'U & "ja"' is not assignable to type 'U extends SupportedLanguage ? U : "ko"'.ts(2322)
It appears that I need to find a way to narrow down this to
U extends SupportedLanguage ? U : "ko"
Is there a solution to achieve the desired functionality without resorting to type assertion?