Reputation: 43
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.
Upvotes: 4
Views: 452
Reputation: 1074038
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...
Upvotes: 6
Reputation: 249476
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[]'
}
Upvotes: 5