Home > database >  Typescript is "over infering"
Typescript is "over infering"

Time:06-26

Consider the following code:

interface classAOptions {
    optionA?: string
}

abstract class Base<TOptions extends classAOptions = classAOptions> {
    protected options: TOptions;

    constructor(options: TOptions) {
        this.options = options;
    }

    updateOptions(options: Partial<TOptions>) {}
}

interface classBOptions extends classAOptions {
    optionB?: string
}

class Extending<TOptions extends classBOptions = classBOptions> extends Base<TOptions> {
    constructor(options: TOptions) {
        super(options);
    }
}

const bInstance = new Extending({
    optionB: 'test'
});

/** Why can't I see "optionA" here? */
bInstance.updateOptions({
    optionA: 'something else'
});

The problem is, that if I create a class with a generic option method, to have the possibility, to expand it further, typescript somehow infers the generic on instantiation, and forgets about the rules I set.

In the above situation, typescript, somehow, infers that my bInstance, is a type of Extending with the generic set to an object which only defines the optionB property. Because of this, later on, when I try to use the updateOptions method, inherited from the abstract Base class, the input parameter only accepts the optionB parameter.

How could I achieve, the following things:

  1. when I use the updateOptions method from the bInstance, I would like to allow the usage of both the classAOptions and classBOptions interface - in other words, I would like to be able to set the optionA property, even though it was not set at instantiaton
  2. I would like to achieve this, without having to extend the updateOptions function in Extending class

Is this possible somehow?

Here's a playground link.

CodePudding user response:

You just have to specify the generic parameter when instantiating:

const bInstance = new Extending<classBOptions>({
    optionB: 'test'
});

/** Why can't I see "optionA" here? */
bInstance.updateOptions({
    optionA: 'something else'
});

CodePudding user response:

You could also change the definition of updateOptions:

updateOptions(options: Partial<TOptions & classAOptions>) {}

Playground

  • Related