繁体   English   中英

TypeScript 函数在不期望的情况下通过类型检查

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM