功能输入输出模板类型

时间:2019-05-31 17:24:58

标签: typescript

我看到了如下定义的有效模板函数类型:

type func = <I, O>(data: I) => O;

我知道此模板在某种程度上适用于通用输入和输出类型,但是我无法弄清楚它如何实际使用...

有什么例子吗?我无法提出与此类模板匹配的声明。还是根本不是模板?我对语法感到困惑。

1 个答案:

答案 0 :(得分:1)

我不确定您在哪里看到了该类型,但是它是表示<{3}}的具体类型:

type Funky = <I, O>(data: I) => O;

如果您具有类型Funky的函数,则可以在任何所需类型的绝对单个参数上调用它(因为I不是generic function),并且可能产生您想要的任何类型的输出(O也不受约束)。

您已经注意到,很难想象这样的功能。在类似Haskell的更合理类型的语言中,它将是constrained而没有一些impossible to implement that。 TypeScript使您可以evil magic进行几乎所有操作,因此您可以编写没有编译器警告的实现,但这仍然是一个非常不安全的功能:

const unsafeCoerce: Funky = (x: any) => x; // any is an escape-hatch from the type system

在这里,unsafeCoerce仅返回其输入,这意味着它应该允许调用者将其输入强制转换为所需的任何类型,即使那是谎言:

const threeAsString: string = unsafeCoerce(3); // DANGER 
// const unsafeCoerce: <number, string>(data: number) => string

threeAsString.charAt(0); // no error at compile time, TypeError at runtime 

所以我也看不到该功能有什么用。


具有相似含义的外观类型是

type Func<I, O> = (data: I) => O;

这是泛型类型,表示 concrete 函数(或一系列具体函数)。您无法使用类型Func的函数,因为它没有指定其通用参数:

const nope: Func = (x: any) => x; // error! 
//          ~~~~ <-- Generic type 'Func' requires 2 type argument(s).

相反,您需要指定参数,该参数成为从某些特定输入类型到某些特定输出类型的函数,这些参数更容易实现:

const stringLength: Func<string, number> = x => x.length; // okay

如果您所做的只是在声明函数时插入IO的具体值,那么这样做就没有多大意义了。但是,出于某些原因,您可能想使用Func<I, O>之类的通用类型,最明显的是在高阶类型的数据类型中。

例如,如果您想制作一个高阶函数apply(f, x),该函数需要一个函数f和一个参数x并返回f(x),您会发现自己想要使用Func之类的类型:

function apply<I, O>(f: Func<I, O>, x: I): O {
  return f(x); // okay
}
const out = apply((x: number) => x.toLocaleString(), 123); // string

有可能您看到Func<I, O>之类的东西,并且记得Funky之类的东西。或者也许某人实际上正使用这样的Funky类型,出于某种邪恶的目的,只有他们知道(除非您查看它在做什么或将其链接到其中)您的问题)。

无论如何,希望能有所帮助。祝你好运!

assert