繁体   English   中英

在 typescript 中,如何定义通用 function 的专用版本?

[英]in typescript, how to define a specialized version of a generic function?

如果我有一个通用的 function:

const f1 = <T>(x: T) => console.log(x)

我可以为 f1 定义一个专门的版本:

const f2 = (x: number) => f1(x)

然后 typescript 如果我这样做会抛出一个错误:

f2('6')

但 f2 实际上是另一个调用 f1 的 function。

有没有办法将 f2 定义为 f1 的专用版本? 就像是:

const f2 = f1<number> // this doesn't work

您可以像这样定义泛型类型

type Fn<T = any> = (x: T) => void

const f1: Fn = (x) => console.log(x)
const f2: Fn<number> = f1
f2('6') // Argument of type '"6"' is not assignable to parameter of type 'number'.

是一个工作游乐场的链接

我将更改您的示例 function 因为类型<T>(x: T)=>void对泛型类型参数没有任何用处,实际上与(x: unknown)=>void相同,a具体 function 型。 相反,让我们看一下<T>(x: T)=>T类型的 function ,它保留输入类型并输出相同类型的值,其中(x: unknown)=>unknown不够:

const f1 = <T>(x: T) => (console.log(x), x);
// const f1: <T>(x: T) => T

const n: number = 6;
const sixNumber = f1(n); // const sixNumber: number

const s: string = "6";    
const sixString = f1(s); // const sixString: string

您要做的是采用通用 function f1并将其用作(x: number)=>number类型的具体 function f2 这是f1类型的扩展,因为<T>(x: T)=>T类型的每个 function 也是(x: number)=>number类型的 function ,反之亦然。 编译器将此识别为有效的扩展,您可以自己将f2注释为扩展类型:

const f2: (x: number) => number = f1; // no error
const sixNumberOkay = f2(n); // okay
const sixStringNotOkay = f2(s); // error! string is not number

所以这很好。

--

现在,正如您所指出的,您不能做的是采用f1的类型和类型number并自动生成f2的类型。 类型系统无法让您表示类型参数的替换类型。 f1<number>typeof f1<number>均无效。 TypeScript 对更高种类的类型没有足够的支持来表达这一点,至少不是纯粹在类型级别

在 TypeScript 3.4 中,TypeScript 引入了对从其他泛型函数推断泛型函数的改进支持 因此,虽然您不能仅在类型级别上进行您所询问的类型操作,但您可以编写一些函数让编译器无论如何都进行该操作。 例如:

function specify<A extends any[], R>(f: (...a: A) => R) {
    return () => f;
}

specify() function 接受任何 function,即使是通用的,并返回一个新的零参数 function,如果原始的也是通用的。 并且调用时 function 将返回原始 function。 这使您可以这样做:

const f3 = specify(f1)<number>(); // const f3: (x: number) => number

specify(f1)返回类型为<T>() => (x: T) => T的 function 。 因此specify(f1)<number>()产生非通用(x: number)=>number function。 它也应该在运行时工作:

const sixNumberStillOkay = f3(n); // okay
const sixStringStillNotOkay = f3(s); // error! string is not number

我不确定您是否会经常将通用函数扩展到具体函数,以使specify()值得; 这取决于你。


好的,希望有帮助; 祝你好运!

链接到代码

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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