Extends from a generic parameter in Typescript

Viewed 71

I am trying to extends a class dynamically. At instantiation of this class, I would like to specify the class it is deriving, not at definition.

Why I need this: I have an interface that contains thousands of fields. I automatically generate implementation classes of this interface depending on the need (one can returns undefined on field member the other raise an exception).

I want a concrete class which will extends those class in generic way:

// This interface is automatically generated
interface AbstractData {
    field?: string;
    // thousands of other fields.
}

// This class is automatically generated
class BaseData implements AbstractData {
    field?: string;
    // thousands of other fields.
}

// This class is automatically generated
class CheckedData implements AbstractData {
    private underlying_field?: string;
    public get field(): string {
        if (this.underlying_field === undefined) {
            throw new Error('field is undefined');
        }
        return this.underlying_field;
    }
    public set field(v: string) { this.underlying_field = v; }
    // thousands of other accessors.
}

class ConcreteData<T> extends T { // Can't do this
    public constructor(data: AbstractData) {
        Object.setPrototypeOf(this, data);
    }

    public get additionalField() { return `field: ${this.field}`; }
}

const data = { field: 'value' };
const b = new ConcreteData<BaseData>(data);
console.log(b.field, b.additionalField);

There are multiple questions in the same vein but no answer seems to fit my need:

The last one got me scratching my head for a while but it does not fit. The "intermediate" class is not specified at instantiation, it still would require to write special versions of ConcreteData for each specialization of the interface. Meaning, if you were to add a third way of accessing the data, you would need a third specialization for ConcreteData. But I intend to have many different type of ConcreteData-like classes against AbstractData which makes this solution impractical.

Is there a way to make a class inherit from a another class based on parameters provided at instantiation and still keep the benefits of the typing system of Typescript?

0 Answers
Related