I have a function identityOrCall
that either calls the function given to it, or returns the value. value
is a generic type.
function identityOrCall <T>(value: T): T {
if (typeof value === 'function')
return value()
else
return value
}
identityOrCall(() => 'x') // -> 'x'
The line identityOrCall(() => 'x')
appears to pass the compiler's type checking.
Why? Shouldn't it give an error?
If identityOrCall
is passed a function, I would expect the generic type T
to be set to Function
and that identityOrCall
should return a Function
type.
Instead I'm able to pass a Function
type as an argument and have identityOrCall
return a string
type.
Why is this? It appears inconsistent to me, but I must be missing something.
The problem is that, since the function return type is not noted anywhere, TypeScript takes its type to be any
. any
is not type-safe; it's assignable to anything. Here, TS extracts T
from the any
return value (since any
can be narrowed down to T).
Best to avoid types of any
whenever possible. I like using TSLint's no-unsafe-any
which forbids this sort of thing.
For similar reasons, the following does not throw a TypeScript error (and is prohibited using the above linting rule), even though it's clearly unsafe:
declare const fn: () => any;
function identityOrCall<T>(value: T): T {
return fn();
}
const result = identityOrCall(() => 'x') // -> 'x'
// result is typed as: () => 'x'. Huh?
If the goal is to have a method behave differently based on the parameters I think the easiest way is to specify overloads
function identityOrCall<T>(value: () => T): T;
function identityOrCall<T>(value: T): T;
function identityOrCall <T>(value: () => T|T): T {
if (typeof value === 'function')
return value()
else
return value
}
const result = identityOrCall(() => 'x') // first overload
const result2 = identityOrCall('x') // second overload
result.split(' '); // No error
result2.split(' '); // No error
result(); // error not callable
When calling the method TS will resolve the signature by going through the overloads until it finds one which matches (meaning order of defining overloads matters here).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.