I don't really know how to ask this question so I think the best way is with an example of what I'm trying to do. Let's say I have the following object:
const obj = {
one: 'some string',
two: new Set<string>(),
};
and now I want to write a function that takes in that object and converts the Sets to Arrays of the same type.
Here's the untyped javascript implementation:
const obj = {
one: 'some string',
two: new Set().add('one').add('two'),
};
function convertToArrays(objWithSets) {
return Object.entries(objWithSets).reduce((objectWithArrays, [key, value]) => {
if (value instanceof Set) {
objectWithArrays[key] = Array.from(value);
} else {
objectWithArrays[key] = value;
}
return objectWithArrays;
}, {});
}
console.log('converted', convertToArrays(obj));
How can I properly type the above function? To clarify: it can take in any object (not just the one, two example) and if it sees a Set<T>, it transforms that to an Array<T>.
I know it requires capturing the type of the inner Set (which is string in this case) and conditionally mapping that type to Array<string>.
Thanks!
You can use a mix of mapped types and conditional types to do this:
Edit: original, overly specific answer below:
Here we go, essentially as you describe:
We allow it to initially be
Set<any>just to serve as a typeguard, and then infer the actual type with the conditional. The conditional narrows toneveron a match failure, which should be fine as the initial check theoretically guarantees the conditional will always evaluate to true.