通用函数类型别名

问题描述 投票:0回答:1

为什么在 TypeScript 中类型别名不能与泛型函数一起使用? 例如,这里 TS 没有将 Identical 类型定义为泛型。

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

const identical: Identical<string> = (v) => v

我知道正确的变体是:

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

但是为什么第一个示例不起作用以及什么类型的

T

typescript
1个回答
13
投票

在下文中,我将使用“特定”一词来表示“非通用”。 通常人们会说“具体”,但我担心有人会认为这意味着“不是

abstract
”,而这与
abstract
类无关。


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

type GenericType<T> = {x: T};

您可以拥有像

Foo<T>
这样的泛型类型,但该类型的任何实际 value 都必须是特定的,实际特定类型指定为
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

请注意,

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


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

type GenericFunction = <T>(x: T, y: T) => void;

泛型函数的类型本身不一定是泛型的;上面的

GenericFunction
名称没有类型参数。 所以你不能通过添加来指定泛型类型参数只有在call函数时才指定泛型函数类型参数:

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

那么,它们之间的区别:

 type IdGenericType<T> = (x: T) => T;
 type IdGenericFunc = <T>(x: T) => T;

第一个是generic类型,指定时将引用specific函数,而第二个是specific类型,它引用generic函数。 这些类型虽然相关,但并不等同。 您可以将

IdGenericFunc
类型的值分配给您想要的任何特定类型
IdGenericType<XXX>
类型的任何变量
XXX

let id: IdGenericFunc = x => x;
let idString: IdGenericType<string> = id; // okay

但反之则不然:

const otherId: IdGenericFunc = idString; // error! T not assignable to string

这是有道理的,因为

IdGenericType<string>
只知道接受和输出
string
:

idString = x => x + "!"; // okay

所以你不能假设

IdGenericType<string>
是有效的
IdGenericFunc
IdGenericType<T>
IdGenericFunc
之间的关系是,
IdGenericFunc
本质上是IdGenericType<T>
交集对于所有可能的
T

// type IdGenericFunc = forall T. IdGenericType<T>; // invalid syntax

但是无法直接用 TypeScript 来表达(我借用了

Haskell
forall 语法)。


请参阅有关泛型值的 TypeScript GitHub 问题,microsoft/TypeScript#17574 了解更多信息。

代码链接

© www.soinside.com 2019 - 2024. All rights reserved.