关于 TypeScript 中【泛型】的问题?

泛型就是一个类型变量,用来存储类型,demo1 最后不应该解析成 demo2 吗?那 demo1 的返回值应该是 string 类型的,为什么会报错呢?

function demo1<T>(): T {
  return '123' // 报错。不能将类型“string”分配给类型“T”。“T”可以使用与“string”无关的任意类型进行实例化。
}
demo1<string>()

---------- 

function demo2(): string {
  return '123'
}
demo2()
阅读 5.3k
3 个回答

泛型,虽然名为“泛”,但实际起到的是声明和约束的作用。

在声明一个函数的时候,如果返回值是无约束的泛型,表示它可以在使用的时候指定(或推断)为任意类型,比如题中定义的 demo1<T>(): T,在使用时可能是这样的

const v1 = demo1<string>();
const v2 = demo1<number>();

第一种情况,在 demo1 里返回字符串是没问题的,但是第二种情况下类型不匹配。定义函数的时候并不知道使用者会传入什么样的类型参数,所以直接把 T 当作 string 来使用是不行的。

如果一个函数完全自主决定返回值,那返回类型在写这个函数的时候就已经明确了,所以不需要使用泛型,直接写成下面这样就对了

function demo1(): string { return "1234"; }

这里还有一个因素是 Runtime 没有类型,不像 C# 可以在运行时拿到类型信息。所以 TS 的类型参数并不能用于业务代码,如果是在 C# 中是可以直接拿类型来用的,比如

// C#
public T Demo1<T>() {
    return Activator.CreateInstance(typeof(T));
//                                  ^^^^^^^^^ 这里可以直接使用 T (C#)
}

那么,在 TypeScript 中仅指定返回类型为泛型其实没什么应用场景,至少需要由函数参数带入这个类型信息并在内部进行计算。比如下面这个示例,在 demo2 中使用了参数 arg,再把它返回出来,这个函数的输出类型 T 和输入类型 T 一致,就可以根据传入的参数来推导

function demo2<T>(arg: T): T {
    console.log(arg);
    return arg;
}

const a: string = demo2("hello");
const b: number = demo2("hi");    // Type 'string' is not assignable to type 'number'.(2322)

泛型不是这么用的,泛型就好比函数参数,是由实际调用时指定的【又或是自动推断】,怎么能由内部逆向推断我这个泛型应该是什么类型,那demo1<string>()这里的string指定的意义什么,我如果期望是number呢,那不是不兼容吗。
其次,你这个例子举得不是很好,如果你的泛型不在参数中使用,那么指定泛型是没什么意义的,完全可以省略,TS会自动推断

泛型是带类型参数的类型,目的是放宽类型约束,延迟到用的时候再确定类型。相当于对类型进行抽象,就像我们抽象通用逻辑一样。

你代码的问题,在于函数返回值确定了是 string,但是声明的返回值是泛型 T,是不确定的:

function demo1<T>(): T {
  return '123' // 报错。不能将类型“string”分配给类型“T”。“T”可以使用与“string”无关的任意类型进行实例化。
}

看一个官方示例,它返回的 result 的类型不是固定的,是传入参数确定的,传入的是 string 返回的就是 Array<string>, 如果传入 number, 返回就是 Array<number>

function createArray<T>(length: number, value: T): Array<T> {
    let result: T[] = [];
    for (let i = 0; i < length; i++) {
        result[i] = value;
    }
    return result;
}

createArray<string>(3, 'x'); // ['x', 'x', 'x']

这里 <string> 可以省去,因为可以自动推导

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题