I'm looking to convert a generic T extends string[]
to a ValueOf<T>
- which would be a union of all possible values in the generic array.
type ValueOf<T extends Array<any>> = unknown;
class Foo<T extends string> {
public value: T;
constructor(value: T) {
this.value = value;
}
}
/**
* Transforms foo type to allow new values and sets foo value to the first element
* of newAllowedValues if the current value does not match it.
*/
function transform<T extends string[]>(foo: Foo<string>, newAllowedValues: T): Foo<ValueOf<T>> {
if (newAllowedValues.length === 0) {
throw new Error('');
}
if (newAllowedValues.indexOf(foo.value) === -1) {
foo.value = newAllowedValues[0];
}
return foo as unknown as Foo<ValueOf<T>>;
}
let foo1 = new Foo<'a' | 'b'>('a');
let foo2 = transform(foo1, ['b', 'c']); // now foo2 should be a Foo<'b' | 'c'>
Currently I could only find a solution for the case where array is a constant: Typescript derive union type from tuple/array values
I know that I could achieve this by using an object rather than an array as newAllowedValues
and relaying on keyof
operator - but it's not pretty and I want to use this for a function that will be frequently used.