interface IYears {
one: string;
two: string;
three: string;
}
function transformYears(years: Array<keyof IYears>): [if all items of "years" includes in keyof IYears] ? IYears : Partial<IYears> {
return years.reduce((acc, year) => ({
...acc,
[year]: 'foo'
}), {})
}
const yearsFirst = transformYears(['one', 'two']) // type of yearsFirst is Partial<IYears>
const yearsSecond = transformYears(['one', 'two', 'three']) // type of yearsFirst is IYears
How modified transformYears
to match type of yearsFirst
and yearsSecond
? And possible check condition "if all items of "years" includes in keyof IYears" in ts?
CodePudding user response:
You need to make the function generic to get this to work.
function transformYears<
Y extends (keyof IYears)[]
>(years: [...Y]): Exclude<keyof IYears, Y[number]> extends never
? IYears
: Partial<IYears>
{
return years.reduce((acc, year) => ({
...acc,
[year]: 'foo'
}), {}) as any
}
If we store the passed array in the generic type Y
, we can use Exclude
to compute the difference between keyof IYears
and Y[number]
. If Y[number]
contains all keys of IYears
, this evaluates to never
which we can check for in the condition.
After thinking about it, we can make it even a bit shorter:
function transformYears<
Y extends (keyof IYears)[]
>(years: [...Y]): keyof IYears extends Y[number] ? IYears : Partial<IYears> {
return years.reduce((acc, year) => ({
...acc,
[year]: 'foo'
}), {}) as any
}