skip to Main Content

Typescript playground link:

class A<T> {
    data: T;
    constructor(data : T){
        this.data = data;
    }

    setData(newData: T) {
        this.data = newData;
    }
}

const instance = new A<void>();
//                           ^ Error: Expected 1 arguments, but got 0.
instance.setData();
//               ^ no error

Here, the type parameter is set to void for the instance of class A. This sets both the constructor’s data parameter and setData‘s newData parameter to type void.

The constructor throws an error that data param is not optional, but setData works fine if you don’t pass any value as an argument. Even though the type of the param is same, the behaviour seems to be different.

Why is this the case? How can I make constructor’s param optional too, but only for void cases?

2

Answers


  1. The absence of a value is valid in the setData method because it is explicitly defined as an overloaded method with a signature that accepts no parameters. This allows you to call setData() without providing any arguments.

    On the other hand, the constructor does not have an explicit overload that accepts no parameters. By default, a constructor without any parameters is expected to be called with the required arguments. If you want to make the constructor parameter optional, you need to define an overload that explicitly allows for the absence of a value.

    When calling the setData method on the instance object without any arguments, the setData method is defined to accept a parameter of type T, which in this case is void. Since void represents the absence of a value, you are allowed to pass no arguments to the setData method.

    To make the constructor parameter optional for only void types, you can use conditional types and function overloads.

    class A<T = void> {
      private data: T;
    
      constructor(data?: T) {
        this.data = data as T;
      }
    
      setData(data: T): void;
      setData(): void {
        // ...
      }
    }
    

    Now, when creating an instance of A, you can omit the constructor argument for void types:

    const instance = new A<void>(); // No param needed
    instance.setData(); // No param needed
    

    And if you specify a non-void type argument, you will need to provide the parameter:

    const instance = new A<string>("Hello"); // Constructor param is required
    instance.setData("World"); // Param is required
    
    Login or Signup to reply.
  2. You have assigned your class A with a constructor included a parameter. So you need to use an empty constructor or add the parameter when initialize it, or make it "really optional" by adding a question mark after the class, no matter what type you gave the class (error of the final line won’t show because the wrongly you initialize the constant). See the example below:

    class A<T> {
        data: T | undefined;
            
        constructor(data?: T){
            this.data = data;
        }
        
        setData(newData?: T) {
            this.data = newData;
        } 
    }
    const instance = new A<void>(); 
    instance.setData();
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search