Vasek - Tom C.
Vasek - Tom C.

Reputation: 241

Conditional required parameter

I'm actually stuck on a funny problem.

I would like to have the following behavior:

const callback = <ErrorType extends Error | null>(err: ErrorType, result?: (ErrorType extends null ? number : undefined)): Error | number => {
    if (err) {
        return err;
    }
    return result;
}

I know this callback is useless but conditional required parameter is interesting:)

Actually, I got 2 errors:

  Type 'Error | null' is not assignable to type 'number | Error'.
    Type 'null' is not assignable to type 'number | Error'.
      Type 'ErrorType' is not assignable to type 'Error'.
        Type 'Error | null' is not assignable to type 'Error'.
          Type 'null' is not assignable to type 'Error'.

     return err;

And

Type '(ErrorType extends null ? number : undefined) | undefined' is not assignable to type 'number | Error'.
  Type 'undefined' is not assignable to type 'number | Error'.

  return result;

I don't really understand why I got those errors.

The things is that if I got an error, I'll never return result and I verify previously with if (err) that error is not null so I just can't return null. Same for number, with my extends, I'm sure that number will never be undefined...

I think it's a problem of inference. I'm doing something bad, but I don't find where.

Thank you :P

Upvotes: 2

Views: 131

Answers (1)

Vasek - Tom C.
Vasek - Tom C.

Reputation: 241

Thanks to Aleksey L.

The correct code is

/**
 * Callback type on error
 * 
 * @param err {Error} - Error object
 * @param result - No result
 * @return Error 
 */
function callback(err: Error, result?: undefined): Error;

/**
 * Callback type on success
 * 
 * @param err {null} - No error
 * @param result {number} - Result
 * @return result
 */
function callback(err: null, result: number): number;

function callback(err: any, result: any): any {
    if (err) {
        return err;
    }
    return result;
}

function main() {
    console.log(callback(null, 4));
    console.log(callback(new Error('error')));
}

Upvotes: 1

Related Questions