Reputation: 101
I have function overloading
function MyFunc(values: IFirst, type: MyEnum.FIRST): number
function MyFunc(values: ISecond, type: MyEnum.SECOND): number
function MyFunc(values: (IFirst | ISecond), type: (MyEnum.FIRST | MyEnum.SECOND)): number {
if(type === MyEnum.FIRST) {
values.
}
...
}
Why my values inside if
statement is conjunction of IFirst
and ISecond
?
How to get discriminated union behavior here? Without adding type
string to interfaces, but with type argument.
I want my values to be IFirst
in if
statement.
Upvotes: 0
Views: 74
Reputation: 10157
You could wrap parameters in object, so they can be discriminated:
enum MyEnum {
FIRST,
SECOND
}
interface IFirst {
first: number;
}
interface ISecond {
second: number;
}
function MyFunc(param: { value: IFirst, type: MyEnum.FIRST }): number
function MyFunc(param: { value: ISecond, type: MyEnum.SECOND }): number
function MyFunc(param: { value: IFirst, type: MyEnum.FIRST } | { value: ISecond, type: MyEnum.SECOND }): number {
if (param.type === MyEnum.FIRST) {
return param.value.first;
} else {
return param.value.second;
}
}
Upvotes: 1
Reputation: 250226
Variables (or parameters) in this case never narrow one another, they can only narrow themselves.
You can get the discriminated union behavior with a tuple, and you can use tuples in rest parameters to spread the tuple to the parameters. The biggest disadvantage of this is you will have to access the tuple items with numbers.
function MyFunc(values: IFirst, type: MyEnum.FIRST): number
function MyFunc(values: ISecond, type: MyEnum.SECOND): number
function MyFunc(...params: [IFirst, MyEnum.FIRST] | [ISecond, MyEnum.SECOND]): number {
if(params[1] === MyEnum.FIRST) {
return params[0].first;
} else {
return params[0].second;
}
}
Upvotes: 1