`A or B` needs to be collapsed to one definite type at compile time. It is
typically used for parameter types where the compiler sees which type is given
at the calling site. This is not applicable if you want your return values to
have different types at runtime.
There are multiple solutions. First solution is derived types:
type
Base = ref object of RootObj
A = ref object of Base
a_value: int
B = ref object of Base
b_value: int
proc test(arg: int): Base =
if arg < 0: return A(a_value: arg)
else: return B(b_value: arg)
let a = test(10)
let b = test(-5)
Another solution is object variants:
type
RetKind = enum
A, B
Ret = object
case kind: RetKind
of A: a_value: int
of B: b_value: int
proc test(arg: int): Ret =
if arg < 0: return Ret(kind: A, a_value: arg)
else: return Ret(kind: B, b_value: arg)
let a = test(10)
let b = test(-5)