仅接受返回相同类型的函数的打字稿函数

Typescript function that accepts only functions returning the same type

我想创建一个函数check(f),其参数f必须是returns与其参数类型相同的函数,类型将被推断。例如:

check((v: number) => v + 1); // OK
check((s: string) => s.toLowerCase()); // OK
check((v: number) => v.toString()); // Not OK

我尝试了以下方法:

function check<T>(f: (v: T) => T) { }

check((v: number) => v > 10 ? v : ""); // Shouldn't be OK

奇怪的是,此代码确实在 TypeScript playground(运行s TypeScript 3.5.1)中报告了错误,但在我的 VS Code([=45] =]s TypeScript 3.6.2),它将通用参数 T 推断为 <number | "">。发生这种情况是因为一些最新的变化吗?如果是这样,我怎样才能仍然编写所需的 check 函数?

更新

以下是重现问题的步骤:

  1. 创建一个空文件夹。
  2. 在文件夹内创建文件test.ts,内容为上述示例代码。文件夹中没有其他文件,因此没有 tsconfig.json,因此所有设置都是默认设置。
  3. 用 VS Code 打开文件夹,然后打开 test.ts。编辑器显示代码没有错误。将光标悬停在 check 函数上方显示它被推断为 check<number | "">.
  4. 打开控制台并运行tsc test.ts。构建成功,没有错误。

你的问题是你没有使用 --strict 编译器选项;具体来说,您需要启用 the --strictFunctionTypes option 才能开始收到您期望的错误。它与 TypeScript 的 3.5 版和 3.6 版无关。您(可能无意中)要求参数双方差,这就是您得到的。

关闭 --strictFunctionTypes 后,函数将不安全地成为 bivariant in their parameter types,这意味着您可以 缩小 它们接受的类型。 扩大它们接受的类型是安全的(因为每个接受 number | "" 的函数也是一个接受 number 的函数,如果我期待后者)但是 narrow 它是不安全的(因为不是每个接受 number 的函数也是接受 number | "" 的函数,你如果我期望后者,真的不应该给我前者)。尽管如此,双变性在某些情况下 很有用 不安全,因此它的某种形式可能会在 TypeScript 中存在,至少会持续一段时间,并且可能永远存在以实现向后兼容性。

除非您想要参数双方差,否则您应该打开--strictFunctionTypes,并且可能只是--strict。希望这能满足您的需求。好的;希望有所帮助。祝你好运!