Home > OS >  How to make return type depend on parameter type
How to make return type depend on parameter type

Time:11-17

i have a method like this public myMethod(param: MyClass | null): MyClass | null i want to somehow communicate, that the output is null only if the parameter is null. so if you pass in an instance of MyClass it will not return null.

what has been tried:

public myMethod<T extends MyClass | null>(param: T): T extends null ? null : MyClass {
  if (param === null) {
    return null;
  }

  return new MyClass(param.cnt   1); // just an example, generally the constructor param is some value derived from the param
}

but that doesn't work - complains that "MyClass isn't assignable to T extendss null ? null : MyClass"

CodePudding user response:

This is a common use case for function overloads. It works by providing a number of separate signatures in addition to the implementation signature.

class Test {
    public myMethod(param: null): null;
    public myMethod(param: MyClass): MyClass;
    public myMethod(param: MyClass | null): MyClass | null {
      if (param === null) {
        return null;
      }

      return new MyClass(); // just an example, generally the constructor param is some value derived from the param
    }
}

The first two signatures are the overload signatures, they will be used to check argument types and determine the return type where you call the method. The last one is the implementation signature, it has to be compatible with the overload signatures and the function implementation but can't be called directly.

CodePudding user response:

Your method accepts T as a parameter, but you also use it as the return type. So if I submit an arbitrary type extending MyClass, I would expect to get my arbitrary type returned if I look at the signature. Typescript prohibits this. If you are not returning the same type as inputted, you can just return MyClass | null.

class MyOtherClass extends MyClass {
    simpleProp: string = 'test';
}

...

const input = new MyOtherClass();
const response = myMethod(input);
console.log(response.simpleProp); // error
// response should be of type MyOtherClass according to the signature,
// but it is actually MyClass.

If you do not intend to return the provided type, just change the return type and when you do nothing with the type information anyway, you can remove generics alltogether.

public myMethod(param: MyClass | null): MyClass | null {
  if (param === null) {
    return null;
  }

  return new MyClass(param.cnt   1); // just an example, generally the constructor param is some value derived from the param
}
  • Related