Issue
I'm trying to figure out if there's a way to use typescript/javascript object destructuring to target only a subset of the objects properties while maintaining the remaining properties of the object in its own variable, "catching all other properties/keys".
My use case is related to using inheritance to extending a class while attempting to leave the api's the similar. In the example below I only want to use object destruction for properties onlyForB
and alsoOnlyForB
while pass all remaining properties to config
variable.
class A {
constructor(config) {
this.name = config.name;
// ...
}
}
class B extends A {
constructor({ onlyForB, alsoOnlyForB, ..config }) { // using ...config doesn't work
this.onlyForB = onlyForB;
this.alsoOnlyForB = alsoOnlyForB;
super(config);
}
}
const b = new B({ onlyForB: "B", alsoOnlyForB: "B2", name: "Satoshi", age: 100});
/**
Trying to achieve the following in class B's constructor
onlyForB -> "B"
alsoOnlyForB -> "B2"
config -> { name: "Satoshi", age: 100 }
*/
When I try this with { onlyForB, alsoOnlyForB, ..config }
which is similar to creating objects with the spread syntax I get errors. In the real use case I am extending an open source class that has mainly "config" properties and using typescript.
Is there a way to achieve this without manually deleting all the object's properties specific to the B
class?
Side Note: For those familiar with python I am trying to achieve something similar to what **kwargs
does, ie. def __init__(self, onlyForB, alsoOnlyForB, **kwargs)
.
Solution
There are lots of possible ways to do something like this; here is one example:
type ConfigForB = {
onlyForB: string,
alsoOnlyForB: string,
age: number,
name: string
}
type ConfigForA = Omit<ConfigForB, 'onlyForB' | 'alsoOnlyForB'>
class A {
private name: string
constructor(config: ConfigForA) {
this.name = config.name;
// ...
}
}
class B extends A {
private onlyForB: string
private alsoOnlyForB: string
constructor({ onlyForB, alsoOnlyForB, ...config }: ConfigForB) {
super(config);
this.onlyForB = onlyForB;
this.alsoOnlyForB = alsoOnlyForB;
}
}
const b = new B({ onlyForB: "B", alsoOnlyForB: "B2", name: "Satoshi", age: 100});
I've defined a ConfigForB
type that has the four properties listed in your example, and used that type in the constructor for B
. Then I've used the Omit<Type, Keys>
utility type to construct a new ConfigForA
type, which is exactly the same as ConfigForB
, except it's without the onlyForB
and alsoOnlyForB
keys.
If I were to define this explicitly, it would look like this:
type ConfigForA = {
age: number,
name: string
}
This would also work, by the way - using Omit
is just nice since you don't have to repeat yourself.
You can try this out on TS Playground here.
Answered By - Donut
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.