返回作为参数提供的函数时保留类型签名
Posted
技术标签:
【中文标题】返回作为参数提供的函数时保留类型签名【英文标题】:Preserving type signature when returning a function that was supplied as a parameter 【发布时间】:2018-09-03 13:55:35 【问题描述】:我有一个名为conditional
的函数,它接收一个布尔值和一个函数,如果布尔值为真则返回该函数,否则返回一个虚拟函数。
function conditional(x, f)
if(x)
return f
else
return () =>
所以,我可以执行如下代码:
let mySqrt = conditional(true, Math.sqrt)
let add = (x, y) => x + y
let myAdd = conditional(true, add)
但是,当我向条件函数添加类型时,提供给conditional
函数的函数的类型签名会丢失。这使得编写 mySqrt("a")
这样的代码成为可能,而不会出现 TypeScript 抱怨。
如何向条件函数添加类型以保留结果函数的类型?
【问题讨论】:
【参考方案1】:你需要使用泛型类型参数来表示函数的类型:
function conditional<T extends (...args: any[]) => any>(x: boolean, f: T): T
if (x)
return f;
else
return (() => ) as any; // we need an assertion here to make the empty function compatible with T
// Usage
let mySqrt = conditional(true, Math.sqrt); //mySqrt will be of type (x: number) => number
let add = (x: number, y: number) => x + y;
let myAdd = conditional(true, add); // myAdd will be of type (x: number, y: number) => number
【讨论】:
虽然 Tao 的解决方案有效,但我发现这个解决方案更通用,更接近我的预期。谢谢!【参考方案2】:您可以结合使用泛型和方法重载签名。
function conditional<T extends Function>(x: true, f: T): T;
function conditional<T extends Function>(x: false, f: T): () => ;
function conditional<T extends Function>(x: boolean, f: T)
if(x)
return f
else
return () =>
let mySqrt = conditional(true, Math.sqrt)
mySqrt('a') // error
当提供重载方法签名时,编译器将隐藏实际的、更灵活的实现。
【讨论】:
虽然在参数常量上以不同的方式键入结果很好,但我认为在这种情况下,期望的结果是能够基于参数选择实现并让其余代码无缝工作的实施。您的实现将根据传入的常量破坏客户端代码,不确定这是意图,但 OP 应该权衡 @TitianCernicova-Dragomir 好点,我度过了一个漫长的夜晚,并没有过多考虑可能的用例。我也没有看到你已经在我面前发布了答案......以上是关于返回作为参数提供的函数时保留类型签名的主要内容,如果未能解决你的问题,请参考以下文章