Within my codebase, I have two unions, A and B, each with a shared unique identifier referred to as key
.
The purpose of Union A is to serve as input for the function called foo
, whereas Union B represents the result yielded by executing the function foo
.
In terms of functionality, it can be guaranteed that foo
will select an element from Union B that has the same key
as the provided Union A.
My goal here is to convey this particular characteristic within the return type definition of foo
.
To better illustrate what I mean, please refer to the following snippet:
type UnionA =
| {
key: "one";
}
| {
key: "two";
};
type UnionB =
| {
key: "one";
value: boolean;
}
| {
key: "two";
value: string;
};
const b: UnionB[] = [
{ key: "two", value: "ok" },
{ key: "one", value: true },
];
function foo(val: UnionA): UnionB | undefined {
for (let i = 0; i < b.length; i++) {
if (val.key === b[i].key) {
return b[i];
}
}
return undefined;
}
const c = foo({ key: "two" });
// The below produces an error:
// Property 'length' does not exist on type 'string | boolean'
//
// But it's actually guaranteed to be a string
console.log(c && c.value.length);
My question now is whether it is feasible to inform TypeScript that the output type of foo
relies on the value specified in the key
attribute of the input parameter?