【问题标题】:TypeScript definitions for ExtJS 5ExtJS 5 的 TypeScript 定义
【发布时间】:2014-08-31 13:26:27
【问题描述】:

有人在为 ExtJS 5 编写 TypeScript 定义吗?我一直在检查DefiniteTyped,但没有任何活动:

https://github.com/borisyankov/DefinitelyTyped/tree/master/extjs

【问题讨论】:

标签: extjs typescript


【解决方案1】:

我开始认真研究这个问题,但发现搜索结果并不令人满意。

首先,here is a small discussion which provides some insight into Sencha's view on TypeScript

虽然我找不到任何特定于 ExtJS 5 的内容(我深表歉意),但我确实找到了 this link,它声称使用以 ExtJS 文档开头的流程生成 TypeScript 声明文件。这些示例针对 ExtJS 4.1,但也许它可以与 ExtJS 5 一起使用。如果是这样,它将解决您的问题。这当然不是答案,但也许是线索。


顺便说一句,上面提到的对话并不适合我。它始于一个看似天真的要求 Sencha 考虑 TypeScript 为静态工具提供的潜力。

打字稿

我刚刚发现了 TypeScript (http://www.typescriptlang.org/),它 看起来很有希望。有人有机会玩它吗? 我想了解是否可以生成 TypeScript 声明文件来声明来自 Ext JS 和 Sencha 的所有类型 触摸框架。我希望有更好的静态分析和工具 支持我的 Sencha 开发工作。

谢谢!

这是 Sencha 高级论坛经理的回复:

让事情变得丑陋的另一件事[TypeScript]

[编辑] 不管我说多少次,这条评论显然是 个人评论,还是个人的。如果你还没有和我说话或 在 Twitter 上关注我或其他任何事情,我对我的代码和 TypeScript(甚至 ES6)的语法很丑。

这太苛刻了!

我个人不认识论坛管理员,所以我不会谈论他对 TypeScript 的特殊偏见。但我确实认为我可以提供一些见解,说明为什么 Sencha 的代表可能不支持它的成功。也许这会帮助您理解为什么对于许多人来说,为 ExtJS 5 创建定义文件可能不是一个高优先级。

请注意,我可能错了,那里有一个 ExtJS 5 定义文件,但它还没有进入 DefinitiveTyped。我的搜索远非详尽。

TypeScript

Here is a simple example of the model of object-oriented programming that TypeScript uses.。请注意,构造函数是一个函数,它返回一个实例,该实例的状态可能已从其原型的状态修改或特化:

function Mammal() {
    //...  
}

构造函数的原型属性,恰好是构造函数返回的对象的原型,然后可以使用方法和属性进行扩展(在 ES5 Object.defineProperty 意义上)。在原型上声明的成员不必为构造函数创建的每个实例重新创建:

Mammal.prototype = function giveBirth() {
    //...
}

从这个意义上说,构造函数扮演着一个类的角色,其原型属性的结构定义了构造函数创建的对象的类型。虽然这种模式在 ES3 和 ES5 中非常冗长,尤其是在添加继承所需的额外机制时,但它是 ES6 用来定义类概念的模式。因此,它是 TypeScript 编译器用来编译类的模式。

如需更完整地处理这种在 JavaScript 中的经典面向对象编程形式,以及使经典继承更简洁的技术,请参阅 this post by Douglas Crockford

值得注意的是,类型的概念仅在设计时存在,并且由 TypeScript 编译器强制执行,以帮助您编写更坚固的代码。

ExtJS

在 TypeScript 出现之前,我已经熟悉 Sencha 的 ExtJS 框架采用的经典继承模型。该模型提供了一种方法来定义类并使用多种模式从其对应类型创建实例,包括模块模式原型模式工厂模式时间>。如果您是 ExtJS 程序员,您会发现这些模式非常熟悉,但作为参考,请参阅 Addy Osmani 的 Learning JavaScript Design Patterns 的相应部分。

作为一个纯 JavaScript 开发者,这种经典的面向对象编程的方法很强大。它在许多方面与 TypeScript 编译器使用的经典面向对象编程模型相似,但有一个关键区别。在 ExtJS 中,类及其类型是框架已知的,因此存在于运行时。 ExtJS 最好的事情之一是它模拟了创建类的语法,就像在 Java 或 C# 中所做的那样。但与TypeScript中指定类的方法相比,就显得苍白无力了。

当我第一次被介绍时,我对 ExtJS 使用的类定义方法非常着迷,以至于我创建了一个自己的库,名为 classical。我受到了足够的启发,创建了自己的库,以便探索和扩展 JavaScript 中的类定义,并为我自己的启迪而实现它。如果您单击上面的链接,您会注意到该项目已经从类似 ExtJS 的类系统演变为 TypeScript 的基类库。

为什么要改变?

首先,TypeScript 提供了一个面向对象的编程模型,它不仅让我能够利用熟悉的 OOP 设计模式,而且还为我提供了一个静态类型系统和与之配套的所有设计时工具。当第一次发现 TypeScript(0.8 版)时,我最初的反应是为经典创建一个类型定义文件,这与为 ExtJS 创建一个类似(但更简单)的努力。在我完成这个任务之后,生成的库的语法是一场彻底的灾难!我想探讨一下出了什么问题,我将使用 ExtJS 中的一个简单示例来做这件事。

这段代码取自上述讨论,看起来像一个标准的 ExtJS 类定义:

Ext.define('WebApp.model.RenderableRecord', {
    extend: 'Ext.data.Model',
    idPropert: 'id',

    isRenderableRecord : true,

    fields: [
        { name: 'id', type: 'string' },
        { name: 'name', type: 'string' },
        {
            name: 'renderable',
            convert: function (val, model) {return val;}
        },
    ],

    renderItems: function (renderer: Function) {
        var me = this;
        return function (config: Object) {
            renderer(me.get('renderable'), config);
        }
    },

});

考虑上面原型定义的接口。如果需要 TypeScript 中的静态类型,可以创建一个看起来像这样的界面:

module WebApp {
  module model {
    export interface RenderableRecord extends Ext.data.Model {
      idPropert: string;
      isRenderableRecord: boolean;
      fields: Array<Field>;
      renderedItems(renderer: Function);
    }

    //Assume Ext.data.Model and Field are defined already
    //and that the Field interface looks something like this:
    export interface Field {
      name: string;
      type: string;
      convert: Function;
    }
  }
}

不仅该接口必须与 ExtJS 定义一起定义,而且实例的类型必须指定两次,一次作为 WebApp.model.RenderableRecord(或者在调用 Ext.create 时作为同名字符串)然后再次将其转换为适当的 TypeScript 类型。获得静态类型需要做很多工作,也就是说,由于强制转换,仍然容易出错!

那么问题出在哪里?

问题是有两种类型系统在起作用。一种是由 TypeScript 编译器强制执行的设计时类型系统。另一种是ExtJS定义的运行时类型系统。这两种类型系统在实现方式上非常相似,但它们都有不同的语法,因此必须单独指定。如果必须维护每个接口的两个副本,则静态类型系统的大部分价值都会丢失。

Here is a more complete treatment of the hurdles that one must overcome when integrating TypeScript and ExtJS。它还引用了上面的 GitHub 项目。作者的结论是

不幸的是,TypeScript 和 ExtJs 似乎不太好用 在一起。

底线是 ExtJS 和 TypeScript 都定义了自己的类型系统,它们的规则并不完全一样。因此 ExtJS 和 TypeScript 从根本上是不兼容的......

...好吧从根本上说这个词太强了,但是要有效地同时使用这两个工具需要做很多工作。所以如果我是 Sencha 的高级论坛经理,我可能也不会支持 TypeScript。

就个人而言,我更喜欢 ES6 预览版、静态类型系统和 TypeScript 提供的设计时工具。遗憾的是,我什至不得不选择,因为两者的类型不同——一个是框架,另一个是语言。有些人肯定会go to great lengths to make them compatible

ExtJS 是一个强大的 JavaScript 框架,我敢肯定它只会随着时间的推移变得更加丰富。但事实上,ExtJS 在用作 JavaScript 框架时是最好的。或者引用同一个论坛经理的话:

...您可以编写正确且高效的 JavaScript,而无需 任何编译器,如 coffeescript 或 typescript。

ExtJS 提供了一种在 JavaScript 框架中实现经典的面向对象继承的方法。 TypeScript 作为一种语言提供了第二种方法。如果您对 TypeScript 感兴趣,请查看 classical。它与 ExtJS 之类的专业框架相去甚远,但它确实提供了关于为 TypeScript 开发人员构建工具时的外观。

【讨论】:

  • 虽然我同意'full on' TS 不能很好地与 Ext 配合使用,但还有其他选择。我已将 Ext 4.2 应用程序转换为 TS,效果很好。我使用 TS 模块,但使用 Ext 类系统。最大的优势是 TS 的参数和局部变量类型检查,这些对我来说是一个巨大的福音。我想我将 TS 用作“类固醇上的 JsHint”,但它非常有帮助。
  • 与'full on' TypeScript 相比,本地语法和原始类型检查的收益相对较小,TypeScript 具有强大的类型推断系统,可以跨越多文件应用程序。如果基本的 TypeScript 功能与 ExtJS 一起使用,那就太好了。但如果是这样的话,想想在整个应用程序的许多文件中进行这种级别的类型推断切割会有多美好。相比之下,Kendo-UI 提供了一个兼容 TypeScript 和 Angular 的专业 JS 库,我认为它正在努力成为一个“现代”的 JavaScript 框架。
  • 谢谢,我去看看 Kendo-UI。我在使用 Ext(与 TS 无关)时遇到的一个大问题是它们缺乏回归测试。 4.2.0 和 4.2.1 是一个痛苦的世界!
  • 相反,我真的很喜欢 ExtJS 的精心设计和工艺水平。但从本质上讲,它是针对它进行优化的——一种动态语言。
  • 这太糟糕了,因为坦率地说 TypeScript 对我的组织来说比 ExtJS 更有价值。
【解决方案2】:

我最近一直在为 ExtJS 编写一些 Typescript 定义,并为另一个提供与 ExtJS 更兼容的分叉 Typescript 编译器的项目做出贡献。

https://github.com/fabioparra/TypeScript

【讨论】:

  • @gareth Man,这是巨大的,恭喜。你能用打字稿的import代替ext的requires吗?
【解决方案3】:

请去寻找 ExtTS - Sencha Ext JS 的高级 TypeScript 类型定义

https://github.com/thanhptr/extts

几乎所有最新版本的 ExtJS 4.x、5.x、6.x 都支持,目前最新版本为 6.0.2.437。

您可以从 ExtJS API 文档中找到的所有内容都在具有强类型支持的类型定义中(例如:Ext.dom.Element、ButtonConfig、..)

【讨论】:

  • 这在理论上可以回答这个问题,但最好将答案的基本部分包含在此处以供将来的用户使用,并提供链接以供参考。 Link-dominated answers 可以通过link rot 失效。
  • @Thanh-Pham:感谢您的链接。您目前是否正在使用这些声明来开发生产系统?
【解决方案4】:

ExtJS TS 定义肯定有空间 虽然 TypeScript 和 ExtJS 确实使用不兼容的类系统,但可以使用一些策略作为解决方法:

使用修补过的 TS 编译器

由 fabioparra 开发并由 Gareth 在此处链接的 ExtJS 发射器是一种可能的解决方法。 恕我直言,主要缺点是它使与支持 TS 语言的 IDE 的集成变得复杂。例如,没有关于此解决方案与现有 Eclipse TS 插件的兼容性的文档。 此外,不确定是否会为 TypeScript 的未来版本维护补丁的开发。

使用 TS 静态方法作为 ExtJS 对象的工厂

这里的想法是提供一组静态方法来替换 ExtJS 类的构造函数。因此,可以在使用旧版 TS 编译器时实例化 ExtJS 对象。 我最近在 github (https://github.com/david-bouyssie/TypExt) 上提供了这个名为 TypExt 的替代解决方案。 请注意,它必须与正确的 ExtJS TS 定义一起使用 (https://github.com/david-bouyssie/TypExt/tree/master/typescripts)。 目前仅支持 ExtJS 5.1.1,但我计划将 TypExt 的使用扩展到其他 ExtJS 版本。

【讨论】:

    【解决方案5】:

    也许我在东西不再是最新的时候回答了,但是我创建了
    TypeScript definitions for Ext.JS 5, 6 and 7,因为有很多原因
    不要走上面的路:

    • 已修补的 TypeScript 编译器不再处于活动状态。今天的 TypeScript 版本离它还很远。
    • 打补丁的 TS 编译器很酷,但是 TS 编译器项目太复杂,无法维护
      (用于生成 Ext.JS 类)对我来说。
    • https://github.com/thanhptr/extts 上的“Premium TypeScript 定义”有
      很多错误,我的意思是很多。例如,您需要的第一个电话
      Ext.application({}); 无处可去。
    • github.com/thanhptr/extts 中的 JS Docs 包含 HTML 语法,对于日常工作来说不太可读。
    • github.com/zz9pa/extjsTypescript 上的 Ext.JS TypeScript 生成器太简单且不可能
      用于更高的 Ext.JS 版本(5、6 和 7),但它是创建的主要动力
      新的Ext.JS TypeScript definitions generator在这里。

    我的解决方案基于与这篇博文相同的原则:“Using ExtJs with TypeScript”。
    但是有一些不同之处。我认为所有差异都可以从示例中清楚地看出:

    主要区别在于:

    • 所有类都是按原样生成的。
    • 还会生成“覆盖”文件中的所有成员。
    • ExtExt.Array 等单例类也可以正确生成。
    • 类配置放在*.Cfg接口中,例如:
      Ext.panel.PanelExt.panel.Panel.Cfg中有配置接口。
    • 要扩展类,您需要的不仅仅是类配置(您需要对象成员,如
      extendrequiresconfigstatics 或模板方法),
      这就是为什么生成的接口也具有扩展类定义的原因:
      Ext.panel.Panel 扩展的类具有在Ext.panel.Panel.Def 中定义的接口。
    • 还有以更好的方式生成的self 属性。
    • 有为监听器/事件生成的接口,例如: Ext.panel.Panel 具有Ext.panel.Panel.Events 中的事件接口。
    • 还为结构化方法参数等生成了大量接口。

    当然可以使用现代工具包创建应用程序,但 Id 没有做任何示例:-)。

    该解决方案支持随处自动完成和Visual Studio代码CTRL+R重构,非常实用:-)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-25
      • 1970-01-01
      • 2014-11-13
      • 1970-01-01
      • 2014-12-20
      • 1970-01-01
      相关资源
      最近更新 更多