Reputation: 897
I have the following interfaces:
interface TxInterface {
field1: string;
field2: string;
field3: number;
}
interface RxInterface {
field1: string;
field2: string;
field3: number;
field4: string;
field5: string;
}
When I receive an object from server, it is typed with RxInterface. In my App, I continue to use this object when I update values for instance.
When I would like to update object in server, I shall send "TxInterface", that contains some fields of "RxInterface".
So, how can I easily to merge my object from RxInterface to TxInterface before send and take only the fields of TxInterface?
Upvotes: 1
Views: 862
Reputation: 329953
There's no way to do this merely with the interface definitions, since such definitions are part of the type system which is erased by runtime. If you need something done at runtime, you need to write code which does it at runtime. In this case, here's a generic function which extracts just the properties of an object matching a list of keys:
function extract<T extends object, K extends keyof T>(
obj: T,
keys: K[]
): Pick<T, K> {
const ret = {} as Pick<T, K>;
keys.forEach(k => ret[k] = obj[k])
return ret;
}
And for your specific use case, you can make a conversion function whose types involve RxInterface
and TxInterface
, but which specifies the particular keys you care about as values and not types:
const rxToTx = (rx: RxInterface): TxInterface => // type annotation here
extract(rx, ["field1", "field2", "field3"]); // explicit key values here
And you can verify that it works:
const rx: RxInterface = {
field1: "yes",
field2: "yep",
field3: 100,
field4: "no",
field5: "nope"
}
const tx = rxToTx(rx);
console.log(tx);
// {field1: "yes", field2: "yep", field3: 100}
Hope that helps; good luck!
Upvotes: 1
Reputation: 4104
All right. It is a good starting point to introduce binary operations also known as "reductions".
Consider generic function signature: T -> T -> T
. What it does is takes two parameters of the same type T
and somehow "collapses" them into a single resulting instance of the same type T
. As a trivial example, take +
on number
s or concatenation on the string
s.
It turns out that such a binary operation is unbelievably common across various branches of math and founded on a much more reliable reasons then just a programming convenience. For example, a "semigroup" is essentially the same binary operation with few additional properties, I won't explain here.
So, don't ignore it. Rather design you code in such a way that you can leverage binary operations of the abovementioned (generic) signature. The question is: how? Mapping! Have you ever heard something about "map/reduce" approach? That's exactly what you are about to implement: firstly map a non-reducible instance into a reducible one and then apply one of reductions you have in order to compute final result.
P.S. In your case mapping since to be trivial: just specify explicitly generic params, since a wider interface is also satisfies narrower interface.
Upvotes: 0