Say I have this code:
interface A {
type: 'a',
value : number
}
interface B {
type: 'b',
value: string
}
type AB = A | B;
const db: Record<string, AB> = {
param1: { type: 'a', value: 1234 }
};
I have code like this (over-simplified) that works well
function processParameter(parameter: string, expectedType: 'a' | 'b') {
if (expectedType === 'a') {
const result = db[parameter];
if(!result) { throw new Error('Not found'); }
if(result.type !== 'a') { throw new Error('Unexpected type'); }
processA(result);
}
if (expectedType === 'b') {
const result = db[parameter];
if(!result) { throw new Error('Not found'); }
if(result.type !== 'b') { throw new Error('Unexpected type'); }
processB(result);
}
}
function processA(value: A) {
// ...
}
function processB(value: B) {
// ...
}
I would like to refactor the code like this:
function processParameter(parameter: string, expectedType: 'a' | 'b') {
if (expectedType === 'a') {
const result = getAndCheck(parameter, expectedType);
processA(result);
}
if (expectedType === 'b') {
const result = getAndCheck(parameter, expectedType);
processB(result);
}
}
// I don't want to write all those lines here, is there a way ?
function getAndCheck(parameter: string, expectedType: 'a'): A;
function getAndCheck(parameter: string, expectedType: 'b'): B;
function getAndCheck(parameter: string, expectedType: 'a' | 'b'): AB {
const result = db[parameter];
if(!result) { throw new Error('Not found'); }
if(result.type !== expectedType) { throw new Error('Unexpected type'); }
return result;
}
Is there a way to simplify that ? Using generic ? using inference ? am I going the wrong way ?