Home > Net >  Typescript: Specify a parent class type to his childs
Typescript: Specify a parent class type to his childs

Time:12-28

Problem

I want to create a JSON object that has 3 kinda of objects (all from the same parent object) as values. And, I want to specify their types. I want to do this to the Intellisense help-me with my code using the functions from the parent class...

Example:

abstract class Parent{
    function do_something() {...}
}

class child_1 extends Parent{}
class child_2 extends Parent{}
class child_3 extends Parent{}

// Now the JSON
const json: {[key: string]: /*WHAT_TO_PUT_HERE*/} = {
    'child_1': child_1,
    'child_2': child_2,
    'child_3': child_3,
}

CodePudding user response:

I assume that by "JSON object" you mean a JavaScript object, since that's what your example code includes. I also assume that you intend each value you in the object to be an instance of one of the child classes rather than the class itself.

TypeScript should already infer the type of your json object, and if you have your editor configured to use TypeScript's language server, you'll get IntelliSense suggestions for methods on each value in the object.

Here is a cleaned up version of your example to demonstrate:

abstract class Parent {
  parentMethod() {}
}

class Child1 extends Parent {
  child1Method() {}
}

const children = {
  child1: new Child1(),
};

// Both of these methods on `child1` will be suggested by Intellisense
children.child1.parentMethod();
children.child1.child1Method();

If you want to enforce that every value in the object is a Parent, you can type it like this:

const children: { [index: string]: Parent } = {
  child1: new Child1(),
  child2: new Child2(),
  child3: new Child3(),
};

However, if you do it this way, you'll only be able to access the methods from Parent on the child1 property, because you've typed the property as a Parent rather than as a Child.

If you don't want to widen the type of each property to Parent, you'll have to specify the index type as a union of all possible children:

const children: { [index: string]: Child1 | Child2 | Child3 } = {
  child1: new Child1(),
  child2: new Child2(),
  child3: new Child3(),
};

If you use this form, you can call the methods from Parent on any of the properties of the object, but you'll need to use a type guard to check which specific class each property is before using any methods that are specific to a particular child class.

  • Related