Take a look at this scenario:
interface BaseArgs {
service: string
}
abstract class BaseClass {
constructor(name: string, args: BaseArgs) {
this.setFields(args)
}
abstract setFields<T extends BaseArgs>(args: T): void
}
interface ChildArgs extends BaseArgs {
newField: string
}
class Child extends BaseClass {
setFields(args: ChildArgs): void {}
}
When I compile this code in Typescript, I encounter the following error:
Property 'setFields' in type 'Child' is not assignable to the same property in base type 'BaseClass'.
Type '(args: ChildArgs) => void' is not assignable to type '<T extends BaseArgs>(args: T) => void'.
Types of parameters 'args' and 'args' are incompatible.
Type 'T' is not assignable to type 'ChildArgs'.
Property 'newField' is missing in type 'BaseArgs' but required in type 'ChildArgs'.
Although I want to ensure that the argument (args) must extend BaseArgs, it seems like simply having Child's setFields method accept a type that extends BaseArgs is not satisfying the compiler. What am I overlooking here?
I experimented with using just T without the constraint, but the compiler recommended adding the extends ChildArgs constraint with
This type parameter might need an extends ChildArgs constraint.
.
I initially hoped that in any subclass extending the abstract base class, setFields could handle any type as long as it extended BaseArgs.