Typescript泛型类型参数:T vs T扩展{}

Typescript泛型类型参数:T vs T扩展{},typescript,generic-type-parameters,Typescript,Generic Type Parameters,下面的两个泛型类型参数在功能上是否有任何区别 函数funcA(){} 函数funcB(){} 我看到它们都被使用过,对它们的区别感到困惑?是的。在funcB中,T必须扩展{},这意味着除{}之外的几乎任何东西。T可以是原语。以下是泛型参数,在以下情况下用于指示函数可以接受的类型参数: function funcA<T>(t: T) { } 我们只能使用扩展T的参数调用funcA。注意:我假设您使用的是TypeScript 3.5或更高版本;在TypeScript 3.5中进行了一

下面的两个泛型类型参数在功能上是否有任何区别

函数funcA(){}
函数funcB(){}

我看到它们都被使用过,对它们的区别感到困惑?

是的。在funcB中,T必须扩展{},这意味着除{}之外的几乎任何东西。T可以是原语。

以下是泛型参数,在以下情况下用于指示函数可以接受的类型参数:

function funcA<T>(t: T) { }

我们只能使用扩展T的参数调用
funcA

注意:我假设您使用的是TypeScript 3.5或更高版本;在TypeScript 3.5中进行了一项更改,从而更改了有关
funcA()
funcB()
之间差异的一些次要细节。我不想通过谈论TS3.4及以下版本中的内容来长篇大论


如果您没有通过
扩展XXX
显式地使用泛型类型参数,那么它将隐式地受到所有类型都可分配到的“顶级类型”的约束。因此在实践中,这意味着
funcA()
中的
T
可以是您想要的任何类型

另一方面,空对象类型
{}
,是一种几乎所有类型都可分配的类型,除了启用时的
null
undefined
。甚至像
string
number
这样的基本类型也可以分配给
{}

所以比较一下:

function funcA<T>() { }
funcA<undefined>(); // okay
funcA<null>(); // okay
funcA<string>(); // okay
funcA<{ a: string }>(); // okay
因此,即使像
string
这样的原语也可以分配给大括号包围的类型,只要这些类型的成员匹配:

const x: { length: number } = s; // okay
如果确实需要表示只接受“true”的类型,即非基本体对象,则可以使用:

但我(认真地)离题了


好吧,希望这会有帮助;祝你好运

function funcA<T>() { }
funcA<undefined>(); // okay
funcA<null>(); // okay
funcA<string>(); // okay
funcA<{ a: string }>(); // okay
function funcB<T extends {}>() { }
funcB<undefined>(); // error
funcB<null>(); // error
funcB<string>(); // okay
funcB<{ a: string }>(); // okay
const s: string = "";
s.toUpperCase(); // okay
const x: { length: number } = s; // okay
const y: object & { length: number } = s; // error
const z: object & { length: number } = { length: 10 }; // okay