Reputation: 9595
I want to discriminate some logic according to what interface my function receives. To do this I'm attempting to use tagged union types, e.g.,
someFunction(arg: TypeA | TypeB): void {
if (arg.kind === "TypeA")
{
// do this
}
else
{
// do that
}
}
where
interface TypeA {
kind: "TypeA";
propertyA: string;
}
interface TypeB {
kind: "TypeB";
propertyB: string;
}
But if I want to call this function, Typescript complains if I don't provide a value for kind, i.e.,
let typeA: TypeA;
typeA = {propertyA: ""}
someFunction(typeA);
with
TS2322: Type '{ propertyA: string; }' is not assignable to type 'TypeA'.
Property 'kind' is missing in type '{ propertyA: string; }'.
So I don't understand how tagged types work if I have to implement the tag (kind
in the example above) every time I want to discriminate. I can only assume I'm using them wrong?
Upvotes: 4
Views: 2719
Reputation: 31600
You can define a type guard to do this. They allow you to tell the type of an argument by the value or existence of one of it's properties.
function isTypeA(arg: TypeA | TypeB): arg is TypeA {
return (<TypeA>arg).propertyA !== undefined;
}
function someFunction(arg: TypeA | TypeB): void {
if (isTypeA(arg))
{
arg.propertyA;
}
else
{
arg.propertyB
}
}
You can read more about them here and check a working example here.
Upvotes: 5