The abstract class AbstractPanelComponent
has a config
object that stores some configuration information. When I extend the abstract class, I want to be able to extend the type of config
to add custom configurations that are required for the implementation.
// Default Config Type
export type DefaultPanelConfig = {
name: string
}
// Type I want to use for extending (to add additional info)
export type CustomConfig = {
additionalConfig: string;
}
@Component({template: ''})
export abstract class AbstractPanelComponent {
config: Partial<DefaultPanelConfig> = {};
}
@Component(...)
export class APanelComponent extends AbstractPanelComponent {
// TODO: Expand the allowed Config somehow...
override config: Partial<CustomConfig & DefaultPanelConfig> = {}
}
Using override config
serves its purpose, but doesn't seem to be a good style. Is there a better way to implement such a config function, or is this already a good way? For example, I thought about using generics and something like <T extends Partial<DefaultPanelConfig>>
, but I couldn't really figure out how I would use that. I look forward to your feedback!
You could use generics to make it more elegant. The trick is, that you can directly use Partial<T & DefaultPanelConfig>
as your DefaultConfiguration
. By doing so, you can easily extend it with a generic type and set a default generic type so that you don't have to extend it.
In the following you can see a sample implementation:
// Default Config Type
type DefaultPanelConfig = {
name: string
}
// Panel Configuration (Generic, so that it can easily be extended)
// Intersect the default panel configuration with the generic to easily extend it
type PanelConfiguration<T = {}> = Partial<T & DefaultPanelConfig>
// Declare AbstractPanelComponent and set the generic to empty object by default.
abstract class AbstractPanelComponent<T = {}> {
config: PanelConfiguration<T> = {};
}
/* From here on: Two Test Cases */
// Testing "Default" PanelConfiguration
class APanelComponent extends AbstractPanelComponent {
// No generic type: Use DefaultPanelConfig and nothing more
override config: PanelConfiguration = {
name: "Custom Configuraton", // Valid
/* additionalConfig: "More Configuration", */ // Invalid (as supposed to)
/* invalid: "invalid" */ // Invalid (as supposed to)
}
}
// Declare Custom Config for testing
type CustomConfig = {
additionalConfig: string;
}
// Testing Extending "Default" Panel Configuration with Custom Configuration
class BPanelComponent extends AbstractPanelComponent<CustomConfig> {
// Expand the Config by simply adding the Generic Type
override config: PanelConfiguration<CustomConfig> = {
name: "Custom Configuraton", // Valid
additionalConfig: "More Configuration", // Valid
/* invalid: "invalid" */ // Invalid (as supposed to)
}
}