【问题标题】:Do Typescript generics use type erasure to implement generics?Typescript 泛型是否使用类型擦除来实现泛型?
【发布时间】:2014-08-19 15:04:33
【问题描述】:

意思是你不能用这样的东西?

class Helpers
{
    static ObjectAs<T>(val: any): T {
        if (!(val instanceof T)) {
            return null;
        }

        return <T>val;
    }
}

获取泛型声明的基础类型的任何解决方法?

更新 1:

正如 Ryan Cavanaugh 所提到的,在编译时,整个类型系统都会被擦除,更像是 Java 的泛型实现。我相信在编译代码中保留类型信息的泛型的 .Net 实现比 Java 更好。 但是,我不禁想知道,为什么不能在 TypeScript 中允许对泛型类型和泛型类型参数进行完整的运行时自省?为什么 TypeScript 的设计者决定在运行时移除所有泛型类型信息?

以下 TypeScript 代码:

function As<T>(n: any): T {
    if (n instanceof T) {
        return n;
    } else {
        return null;
    }
}

var obj: Object = 1;
var x = As<number>(obj);

可以翻译成这段 JavaScript 代码:

function As(n, T) {
    if (n instanceof T) {
        return n;
    } else {
        return null;
    }
}

var obj = 1;
var x = As(obj, Number);

在运行时保留类型信息并与js代码兼容!

更新 2: 我已经在 CodePlex 上发布了这个问题,希望能从 TypeScript 人那里得到更多 https://typescript.codeplex.com/discussions/550262

【问题讨论】:

  • 多么棒的问题...希望它不会关闭 SO 风格
  • 规范的第 2 页指出,在编译器发出 JavaScript 之前,所有类型信息都会被擦除。鉴于这些信息,我最好的猜测是您的 instanceof 运算符在运行时环境中将毫无意义。我最好的建议是在他们的论坛中创建一个讨论规范的帖子:typescript.codeplex.com/discussions/topics/5488/…。如果还没有,你可能会让他们考虑支持这个。
  • @ErikNedwidek 已经在上面了 :)
  • 你不能按照你的建议去做,因为你可以在运行时动态调用函数,所以转译器不一定知道将对As(n)的调用转换为As(n, T)。更不用说它会用大量现有的 TypeScript 代码进行重大更改。另外,当 T 是数字、字符串或布尔值时会发生什么?你不能在上面调用instanceof,也不能作为参数传入。您必须实现一些 TS 要求,即如果在函数内部调用 instanceof,您的泛型必须是类且不能是原语。

标签: generics typescript


【解决方案1】:

类型系统被完全删除。您可以在任何通用函数的生成代码中看到这一点。

也就是说,对于类,还剩下一些运行时信息。你可以这样写:

class A { }
class B { }
function As<T>(n: any, type: { new(...args: any[]): T }): T {
    if(n instanceof type) {
        return n;
    } else {
        return null;
    }
}

var x = new A();
var y = new B();
console.log(As(x, A));
console.log(As(x, B));

【讨论】:

  • 在运行时使用类型参数来保留类型非常有意义,但是我想知道为什么 TypeScript 设计者决定在生成的 js 代码中完全删除泛型类型?查看原帖中的更新
  • @KamyarNazeri “在运行时使用类型参数来保留类型非常有意义”。但是 Javascript 不是鸭式语言吗?由于目标环境没有类型的概念,因此完全类型擦除非常有意义。
  • @Aron 我相信你误读了我的意思。考虑到方法签名被保留, type 参数 被保留在编译的 js 文件中!然而,它是通用类型声明——当方法签名中不存在时——被类型擦除删除。此外,JavaScript 确实是一种鸭式语言,但是 TypeScript 是 JavaScript 的超集,我相信泛型类型擦除可能会有更多问题
  • 本次更新假定类型系统中的所有类型都由对应的构造函数表现出来,但肯定不是这样——匿名类型、接口等都没有明显对应的运行时对象对他们
  • @RyanCavanaugh 我已经在 codeplex 上发布了这个问题,你能更具体一点吗:typescript.codeplex.com/discussions/550262
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-11
  • 2019-05-30
相关资源
最近更新 更多