Typescript泛型、约束和文字类型

Typescript泛型、约束和文字类型,typescript,typescript-generics,Typescript,Typescript Generics,我有以下通用功能: type Identity = <T extends string | number>(arg: T) => T; const identity: Identity = (x) => x; 我希望从identity返回的类型可以是字符串或数字,但是我似乎正在从'a'和1返回文本类型。为什么会这样?有没有办法改变我的约束,这就是我的行为 我已经找到了一些解决办法。首先,要首先将参数指定给变量,请执行以下操作: let a_param = 'a' let

我有以下通用功能:

type Identity = <T extends string | number>(arg: T) => T;
const identity: Identity = (x) => x;
我希望从
identity
返回的类型可以是
字符串
数字
,但是我似乎正在从
'a'
1
返回文本类型。为什么会这样?有没有办法改变我的约束,这就是我的行为

我已经找到了一些解决办法。首先,要首先将参数指定给变量,请执行以下操作:

let a_param = 'a'
let a = identity(a_param);
a = 'b'; // Yay

let b_param = 1;
let b = identity(b_param);
b = 2; // Yay
第二,转换为
字符串
数字

let a = identity('a' as string);
a = 'b'; // Yay

let b = identity(1 as number);
b = 2; // Yay

这两种感觉都不对。我还在学习TS,所以我想我错过了一些东西。

类型参数通常会被推断为与参数一致的最具体的可能类型;在本例中,字符串文本类型
'a'
。这几乎总是人们想要的行为

在您的例子中,推断类型过于严格,因为您将其用作变量的推断类型,而不仅仅是表达式的推断类型。因此,自然的解决方案是指定较弱的类型参数,如下所示:

let a = identity<string>('a');

您使用的是泛型,但您的需求与泛型相反。这是因为
identity('a')
实际上意味着
identity('a')
,因此返回类型是
'a'
(不是任何字符串)

(出于某种原因)有效的方法是:

我认为这是如何工作的,当您调用实现该类型的函数时,它解决了类型
Identity
中哪些重载最匹配

let a = identity<string>('a');
let a: string = identity('a');
type Identity = {
  (arg: number): number;
  (arg: string): string;
}

const identity: Identity = (x: any) => x;

let a = identity('a');
a = 'b'; // yes
a = 3; // no

let b = identity(1);
b = 'b'; // no
b = 3; // yes