edit
Due to course of time, this question has lost its validity, as it seems from the comments and answers to this one. Despite initial appearance, it\
Besides generics you can use function overloading
function getI18n(id: string[]): string[];
function getI18n(id: string): string;
function getI18n(id: string | string[]): string | string[] {
if (typeof id === 'string') {
return id + '_title';
}
return id.slice();
}
const title = getI18n('test'); // const title: string
const titles = getI18n(['a', 'b', 'c']); // const titles: string[]
Link to official docs on this feature: functions overloads
You can achieve the effect by generic type property. Consider:
function getI18n<A extends string[] | string>(id: A): A {
return id; // example implementation
}
const arr = getI18n(['a', 'b']) // arr is string[]
const str = getI18n('a') // str is string
As the solution works great for id function, the issue starts with any implementation, TS is complaining about types as if the only way is to pass arguments without any modifications. Consider:
function getI18n<A extends string[] | string>(id: A): A {
if (typeof id === 'string') {
return id.concat('suffix') as A;
} else {
return (id as string[]).map(x => x.concat('suffix')) as A;
}
}
The solution works nice, but we need to consider some things:
The last point issue can be viewed in the example below:
const str = getI18n('a') // str is type "a"
So output type is "a" but in example implementation result will be a string "asuffix", so the type is wrong.
I want to add one thing to the whole topic. The fact that we have the demand to have such polymorphic input is generally inherited with common JS approach, were such things are considered as historically good practice. But in reality function which has specific one input will be better, it creates less confusion and questions.
Create function with monomorphic type.
function getI18n(ids: string[]): string[] {
return ids.map(id => id + "suffix");
}
const arr = getI18n(['a', 'b'])
const str = getI18n(['a'])
Simple as that. Benefits of the approach:
There is really no cost in putting a string into array brackets.