[英]TypeScript function passes type check when not expected to
我有一个函数identityOrCall
要么调用给它的函数,要么返回值。 value
是一个泛型类型。
function identityOrCall <T>(value: T): T {
if (typeof value === 'function')
return value()
else
return value
}
identityOrCall(() => 'x') // -> 'x'
行identityOrCall(() => 'x')
似乎通过了编译器的类型检查。
为什么? 它不应该给出错误吗?
如果向identityOrCall
传递一个函数,我希望将泛型类型T
设置为Function
并且该identityOrCall
应返回一个Function
类型。
相反,我可以将Function
类型作为参数传递,并让identityOrCall
返回一个string
类型。
为什么是这样? 这对我来说似乎不一致,但我一定错过了一些东西。
问题是,由于函数返回类型没有在任何地方注明,TypeScript 将其类型设为any
。 any
不是类型安全的; 它可以分配给任何东西。 在这里,TS 从any
返回值中提取T
(因为any
可以缩小到 T)。
最好尽可能避免any
类型。 我喜欢使用 TSLint 的no-unsafe-any
来禁止这种事情。
出于类似的原因,以下内容不会引发 TypeScript 错误(并且禁止使用上述 linting 规则),即使它显然是不安全的:
declare const fn: () => any;
function identityOrCall<T>(value: T): T {
return fn();
}
const result = identityOrCall(() => 'x') // -> 'x'
// result is typed as: () => 'x'. Huh?
如果目标是让方法根据参数表现不同,我认为最简单的方法是指定重载
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
调用方法时,TS 将通过重载解析签名,直到找到匹配的一个(这意味着定义重载的顺序在这里很重要)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.