泛型函数类型别名

Dmi*_*kov 3 typescript

为什么在 TypeScript 中类型别名不适用于泛型函数?例如,这里的 TS 没有将 Identical 类型定义为泛型。

type Identical = <T>(v: T) => T;

const identical: Identical<string> = (v) => v
Run Code Online (Sandbox Code Playgroud)

我知道正确的变体是:

type Identical<T> = (v: T) => T;
Run Code Online (Sandbox Code Playgroud)

但是为什么第一个例子不起作用,什么类型的T

jca*_*alz 5

在下文中,我将使用“特定”一词来表示“非通用”。通常人们对此说“具体”,但我担心有人会认为这意味着“不abstract”,而这与abstract课程无关。


除了泛型函数,TypeScript 只有泛型类型,没有泛型。对于泛型类型,类型参数写在类型名称后面的尖括号中:

type GenericType<T> = {x: T};
Run Code Online (Sandbox Code Playgroud)

您可以拥有像 一样的泛型类型Foo<T>,但该类型的任何实际都必须是特定的,实际特定类型指定为T

declare const badValue1: GenericType; // error, requires 1 type argument
declare const badValue2: GenericType<T>; // error, cannot find name 'T'
declare const goodValue: GenericType<string>; // okay
Run Code Online (Sandbox Code Playgroud)

请注意,GenericType<string>现在是特定类型,相当于{x: string}. 因此,一旦通过插入特定类型在泛型类型中指定泛型参数,就会得到特定类型。


泛型函数不同:泛型函数类型的值是泛型的。它充当不同特定功能类型的完整系列。对于泛型函数类型,类型参数写在函数参数列表之前的尖括号中:

type GenericFunction = <T>(x: T, y: T) => void;
Run Code Online (Sandbox Code Playgroud)

泛型函数的类型不一定是泛型本身;GenericFunction上面的名称没有类型参数。所以不能通过添加来指定泛型类型参数,只能在调用函数时指定泛型函数类型参数:

declare const badFunc: GenericFunction<string>; // error, GenericFunction is not generic
declare const goodFunc: GenericFunction; // okay
const ret = goodFunc<string>("okay", "fine"); // okay, type parameter specified as string
const ret2 = goodFunc("okay", "fine"); // also okay, type parameter inferred as string
Run Code Online (Sandbox Code Playgroud)

所以,它们之间的区别:

 type IdGenericType<T> = (x: T) => T;
 type IdGenericFunc = <T>(x: T) => T;
Run Code Online (Sandbox Code Playgroud)

是第一个是泛型类型,在指定时将引用特定函数,而第二个是特定类型,它引用泛型函数。尽管它们是相关的,但这些类型并不等效。您可以为所需的任何特定类型的任何类型IdGenericFunc变量分配类型值:IdGenericType<XXX>XXX

let id: IdGenericFunc = x => x;
let idString: IdGenericType<string> = id; // okay
Run Code Online (Sandbox Code Playgroud)

但反之亦然:

const otherId: IdGenericFunc = idString; // error! T not assignable to string
Run Code Online (Sandbox Code Playgroud)

这是有道理的,因为 anIdGenericType<string>只知道接受和输出 a string

idString = x => x + "!"; // okay
Run Code Online (Sandbox Code Playgroud)

所以你不能假设 anIdGenericType<string>是一个有效的IdGenericFunc. 之间的关系IdGenericType<T>IdGenericFuncIdGenericFunc基本上是交叉点IdGenericType<T> 所有可能的T

// type IdGenericFunc = forall T. IdGenericType<T>; // invalid syntax
Run Code Online (Sandbox Code Playgroud)

但是没有办法直接在 TypeScript 中表达它(我forallHaskell借用了语法)。


有关更多信息,请参阅有关泛型值TypeScript GitHub 问题。好的,希望有帮助;祝你好运!

代码链接