I'm running into a little issue when trying to implement function overloading with TypeScript in conjunction with an enum being passed as a parameter, and a second argument whose type depends on the enum.
For example:
FOO, then the second argument is of a string typeBAR, then the second argument is of a number typeBAZ, there is no second argumentThe code I have is as follow, but somehow TypeScript throws an error because even when I'm checking the first argument against the enum, intellisense does not narrow down the type of the second argument: fieldValue is always string | number.
enum ViewName {
FOO = 'foo',
BAR = 'bar',
BAZ = 'baz'
}
function myFunction(viewName: ViewName.FOO, stringValue: string);
function myFunction(viewName: ViewName.BAR, numberValue: number);
function myFunction(viewName: ViewName.BAZ);
function myFunction(viewName: ViewName, fieldValue?: string | number): void {
if (viewName === ViewName.FOO) {
fieldValue = fieldValue.reverse();
}
if (viewName === ViewName.BAR) {
fieldValue *= 2;
}
if (viewName === ViewName.BAZ) {
return console.log('No fieldvalue is supplied by BAZ.');
}
console.log(fieldValue);
}
The code can also be viewed on TypeScript Playground.
Typescript will not narrow the type of the second parameter based on the type of the first parameter. This feature is just not implemented in typescript.
You can either add extra checks to the if to let the compiler narrow the type of fieldValue
function myFunction(viewName: ViewName.FOO, stringValue: string);
function myFunction(viewName: ViewName.BAR, numberValue: number);
function myFunction(viewName: ViewName.BAZ);
function myFunction(viewName: ViewName, fieldValue?: string | number): void {
if (viewName === ViewName.FOO && typeof fieldValue === "string") {
fieldValue = fieldValue.reverse();
}
else if (viewName === ViewName.BAR && typeof fieldValue === 'number') {
fieldValue *= 2;
}
console.log(fieldValue);
}
Or you can just use a type assertion:
function myFunction(viewName: ViewName.FOO, stringValue: string);
function myFunction(viewName: ViewName.BAR, numberValue: number);
function myFunction(viewName: ViewName.BAZ);
function myFunction(viewName: ViewName, fieldValue?: string | number): void {
if (viewName === ViewName.FOO) {
fieldValue = (fieldValue as string).reverse();
}
else if (viewName === ViewName.BAR) {
fieldValue = (fieldValue as number) * 2;
}
console.log(fieldValue);
}
A bigger change would be to use a discriminated union, that will allow the compiler to narrow the type of the parameter in a more expected way:
function myFunction(p: { viewName: ViewName.BAZ }
| { viewName: ViewName.BAR, fieldValue: number }
| { viewName: ViewName.FOO, fieldValue: string }): void {
if (p.viewName === ViewName.FOO) {
p.fieldValue = p.fieldValue.reverse();
}
else if (p.viewName === ViewName.BAR) {
p.fieldValue *= 2;
}
console.log(fieldValue);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With