Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TypeScript: No error for incorrect function return value

Tags:

typescript

I expected an error for this buggy function (returning an object where an array is expected), but TypeScript did not raise an error:

function foo(bar: boolean, baz: any): string[] {
  return bar ? baz : {};
}

It seems this only occurs when the other ternary branch returns any [1]. Regardless of the any, shouldn't TypeScript be able to detect the error on the other branch?


[1] I know that baz shouldn't be typed as any. This example is derived from an actual project that does not exactly adhere to best practices like this. Also, unknown didn't exist when this code was written.

like image 663
Hendrik Liebau Avatar asked Dec 18 '22 20:12

Hendrik Liebau


2 Answers

When doing type inference, TypeScript picks the best common type (docs). In your example, the compiler has to infer the result type of the conditional expression.¹ The best common type for any and object is any. Since any matches anything, there's no warning.

If you use if instead...

function foo(foo: boolean, bar: any): string[] {
    if (foo) {
        return bar;
    } else {
        return {};
    }
}

...the compiler doesn't have to infer the type of the conditional expression, and reports an error on return {}.


¹ ? : is the conditional operator. It's a ternary operator (an operator accepting three operands, just as a unary operator accepts one operand and a binary operator accepts two), and for the moment it's JavaScript's (and TypeScript's) only ternary operator, but in theory someday there could be another ternary operator added...

like image 79
T.J. Crowder Avatar answered Jan 06 '23 02:01

T.J. Crowder


The problem is bar is of type any. The type of a ternary operation would be a union of both possible result types. In this case that would mean any | {}. But the rules for how unions are resolved dictate that if any is part of the union the whole union just becomes any (this makes sense, if something is any (which is any possible type) or anything else, it can be anything so that would be any).

This would be an error:

function foo(foo: boolean, bar: string[]): string[] {
  return foo ? bar : {}; // Type 'string[] | {}' is not assignable to type 'string[]'
}

Note To avoid such errors, any should generally be avoided, as of 3.0 you should prefer unknown, this would be an error

function foo(foo: boolean, bar: unknown): string[] {
  return foo ? bar : {}; // Type 'unknown' is not assignable to type 'string[]'
}
like image 38
Titian Cernicova-Dragomir Avatar answered Jan 06 '23 02:01

Titian Cernicova-Dragomir