I haven't use Typescript in many years and can't remember nor find how to type guard many classes inside a switch statement correctly.
class A {}
class B {}
class C {}
type OneOfThem = A | B | C;
function test(foo: OneOfThem): string {
switch(/* something using foo */) {
/* A */:
return "A";
/* B */:
return "B";
/* C */:
return "C";
/* should not need to use "default" as all cases are handled */
}
}
I found and tried several options like:
foo.constructor
instanceof
inside the case statementsbut none of them works (Function lacks ending return statement and return type does not include 'undefined'
).
Is my memory playing tricks and this is not possible with classes ?
adding an extra member to the three classes to be used in the switch statement
That is indeed probably the simplest solution for your case: it uses Discriminated Union, by adding a discriminant member to each class, with literal types (i.e. not just string
or number
), so that you (and TypeScript) can tell apart foo
is from which class:
class A {
readonly kind = "a"
// ^? "a" string literal, not just `string`
}
class B {
kind: "b" = "b"
// ^? "b" string literal, as explicitly typed
}
class C {
kind = "c" as const
// ^? "c" string literal, thanks to the const assertion
}
Then simply differentiate based on this kind
discriminant property:
function test(foo: OneOfThem): string { // Okay
switch (foo.kind) {
case "a":
foo
//^? A inferred by TS, based on `foo.kind === "a"` type guard
return "A";
case "b":
foo
//^? B
return "B";
case "c":
foo
//^? C
return "C";
/* should not need to use "default" as all cases are handled */
}
}