Following this article, I'm trying to mimic Rust's Result<T,E>
type in TypeScript, this is the code:
type Result<T, E> =
| { ok: true; data: T }
| { ok: false; error: E };
const Ok = <T>(data: T): Result<T, never> => {
return { ok: true, data };
};
const Err = <E>(error: E): Result<never, E> => {
return { ok: false, error };
};
I want to make it a bit better, so that the Ok()
argument could be optional if the T
type is undefined
, but if I make it optional, all the other types do not enforce argument to be present.
E.g. If I change data: T
argument of Ok()
to be data?: T
, I can use Ok()
with no value.
function testFunc(isOk: boolean): Result<undefined, Error> {
if (isOk) {
return Ok();
}
return Err(new Error("my error"));
}
But I can't enforce other type:
function testFunc(isOk: boolean): Result<number, Error> {
if (isOk) {
// --- Gives me an error (string is not assignable to number)
return Ok('hi');
// --- Doesn't give me an error, but I need it
return Ok();
}
return Err(new Error("my error"));
}
Is it even possible to do something like this, considering I want to only use these two functions Ok
and Err
?
CodePudding user response:
You can try using function overloading:
function Ok<T>(): Result<T | undefined, never>;
function Ok<T>(data: T): Result<T, never>;
function Ok<T>(data?: T): Result<T | undefined, never> {
return { ok: true, data };
}