I have this interface:
interface IInternalListener {
element: HTMLElement,
id: string,
type: string,
listener: EventListenerOrEventListenerObject,
useCapture: boolean
}
And I also want to use this interface:
interface IListener {
element: HTMLElement,
id: string | number,
type: string,
listener: EventListenerOrEventListenerObject,
useCapture: boolean
}
The only difference being the type for id
. I want to employ DRY (Don't Repeat Yourself)
How can I create this without copy paste. A mapped type seems the way to go but in this answer here they are mapping all the props - Typescript: how do you create a Copy of a type but change the property typeings
I only want to change one prop. Anyone know how to do this? I don't have to use mapped types, any viable solution is fair game. TIA
CodePudding user response:
There are a few ways to do this.
Way 1
Extract the common logic into a third interface the other two extend:
interface IWhatever {
element: HTMLElement,
type: string,
listener: EventListenerOrEventListenerObject,
useCapture: boolean
}
interface IListener extends IWhatever {
id: string
}
interface IInternalListener extends IWhatever {
id: string | number
}
Way 2
As Robby Cornelissen points out in the comments, you can use a generic:
interface IListener<T> {
id: T
element: HTMLElement,
type: string,
listener: EventListenerOrEventListenerObject,
useCapture: boolean
}
Way 3
Lets say you don't own the IListener interface and can't change it but you want to reuse a lot of it for your other interface:
interface IInternalListener extends Omit<IListener, 'id'> {
id: string | number
}
CodePudding user response:
You can use extends and Omit
utility type together.
Example
interface IInternalListener {
element: HTMLElement,
id: string,
type: string,
listener: EventListenerOrEventListenerObject,
useCapture: boolean
}
interface IListener extends Omit<IInternalListener, 'id'> {
id: string | number
}
Basically, we will remove the id
property and add it back with the preferred type you need.