In the process of refactoring some code, I encountered a scenario where a function returns different types of content based on the key passed in. Now, I am looking to create a function signature that can accept various types of content depending on the provided key.
To illustrate my dilemma, consider the following simplified example:
type OptionA = { type: 'A'; val: number };
type OptionB = { type: 'B'; val: string };
type Option = OptionA | OptionB;
function process<T extends Option['type']>(type: T, val: Extract<Option, { type: T }>['val']) {
perform({ type, val });
}
function perform(o: Option) {
console.log(o);
}
At first glance, it seems like there are no typing issues with this code snippet. The process
function can only be used in the following ways:
process('A', 1) // No error
process('B', 'a') // No error
process('A', 'a')
// Warning: Argument of type 'string' is not assignable to parameter of type 'number'.ts(2345)
process('B', 1)
// Warning: Argument of type 'number' is not assignable to parameter of type 'string'.ts(2345)
Is there a way to modify the function type signature to eliminate these warnings?
Edit: Further testing has led me to realize that we can simplify the process
function signature as follows without affecting the warning:
function process<T extends Option>(type: T['type'], val: T['val']) {
perform({ type, val });
}