Does anyone know how to convert a generic T extends string[]
to a ValueOf<T>
, essentially creating a union of all possible values within the generic array?
type ValueOf<T extends Array<any>> = unknown;
class Foo<T extends string> {
public value: T;
constructor(value: T) {
this.value = value;
}
}
/**
* Adjusts foo type to allow new values and updates the foo value to the first element
* in newAllowedValues if the current value is not present.
*/
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'>
I've only found a solution when the array is constant: Typescript derive union type from tuple/array values
I'm aware that I can use an object instead of an array for newAllowedValues
and rely on the keyof
operator, but it's not ideal for a frequently used function.