skip to Main Content

I extended a new class form a base class and added some properties.
How can I create an instance of derived class with a given base class including additional props?

This code works but casts the class type and is not Type Safe

How can I do it without type casting?

// Base class is imported from a package. Not editable
class BaseClass {
  public x: number;
  public power() {
    return this.x * 2;
  }
}

export interface CustomClass extends BaseClass {
  value: number;
}

function createCustomClass(base: BaseClass, myValue: number): CustomClass {

  // it's not type safe to cast this variable
  // How to do it the right way in Typescript?
  const result: CustomClass = base as CustomClass;
  result.value = myValue;
  return result;
}

2

Answers


  1. I don’t think it’s possible to completely exclude type casting, using your approach, but it will be safe if you’ll check whether the variable result is valid CustomClass by using type guard(isCustomClass in my implementation):

    // Base class is imported from a package. Not editable
    class BaseClass {
      public x: number;
      public power() {
        return this.x * 2;
      }
    }
    
    export interface CustomClass extends BaseClass {
      value: number;
    }
    
    function isCustomClass(classToCheck: any): classToCheck is CustomClass {
      return (
        typeof classToCheck?.value === "number" && classToCheck instanceof BaseClass
      );
    }
    
    function createCustomClass(base: BaseClass, myValue: number): CustomClass {
      const result = base;
      (result as CustomClass).value = myValue;
      if (!isCustomClass(result)) {
        throw new Error("Cannot create valid `CustomClass`");
      }
    
      return result;
    }
    
    Login or Signup to reply.
  2. You can use the Object.assign() method to add properties to a target object. The method returns the target object, and the return type for its call signature in the TypeScript library is the intersection of the types of the inputs.

    That means your createCustomClass() can be implemented like this:

    function createCustomClass(base: BaseClass, myValue: number): CustomClass {
      return Object.assign(base, { value: myValue });
    }
    

    The return type is BaseClass & {value: number}, which is structurally identical to CustomClass and thus the function compiles without error, and there’s no type assertion needed.

    Playground link to code

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search