typescript
主要用于复杂应用情况下的编程解决方案。当弱类型javascript无法满足这种复杂应用编程环境时。我们就考虑使用typescript
。例如sdk的封装,类库的编写,等等。
当然,写出来的代码浏览器不能直接运行,需要依赖编译器和打包工具。这里我使用的是rollup
。rollup
对于类库的打包非常灵活。假如你之前采用了es6+class的编程方式,那么你转变到typescript
,只需要安装配置一个插件即可。
其次,typescript
对于IDE的错误提示,也是非常的人性化,一读即懂,这是个人非常喜欢的一种方式。
如果你之前有使用过强类型语言,例如java,c#,等等,那么你上手会非常快。
对于使用rollup
的开发者来说。只需要在原有的插件配置中新增rollup-plugin-typescript
插件即可。当然,插件依赖最基本的 typescript包(核心编译器)和tslib包(核心依赖)
npm install --save-dev rollup-plugin-typescript typescript tslib
然后,配置插件即可。
接下来我将项目中的所有.js
结尾的文件全部换成.ts
结尾的文件。然后按照IDE给的提示,一个个修改错误即可。
接下来就记录我修改项目之中产生的问题。
对于原先的直接赋值this来声明类变量的方式将不在适用。需要在类头部声明该变量,再设置其类型。
修改为:
原先的es6 class 语法不支持 private
、public
、protected
等关键字的使用。现在我们可以在typescript中使用。这对于不想暴露类内部变量以及继承的使用,都有着很好的意义和作用。
例如原先我们这么写私有变量(函数)。这简直是欺骗自己。因为这个_init函数在外部还是可以访问。
现在可以这么写:
这样在外部就无法访问到_init函数了。当然这仅仅局限于编译阶段。再编译后生成的对象中,我们任然能够通过类对象去访问_init函数。(吐槽一下,ts本应该能够做处理的,采用闭包的形式)
例如这段ts代码
class A{
private name: string;
constructor(name){
this.name=name;
}
print(){
this.console();
}
private console(){
console.log(this.name);
}
}
let a=new A('jc');
a.print();
编译后:
var A = (function () {
function A(name) {
this.name = name;
}
A.prototype.print = function () {
this.console();
};
A.prototype.console = function () {
console.log(this.name);
};
return A;
}());
var a = new A('jc');
a.print();
可以看到typescript并没有为私有属性和函数做任何处理,但是如果在外部访问了私有变量,在编译时会报错,可见typescript是在编译过程的底层实现了对私有变量的检查。
个人看法,可以通过闭包的形式实现私有变量的编译:
var A = (function () {
var name = ""
function A(name) {
name = name;
}
A.prototype.print = function () {
this.console();
};
A.prototype.console = function () {
console.log(name);
};
return A;
}());
var a = new A('jc');
a.print();
为什么ts不这么做,那就不清楚缘由了。注意对于修饰符,更多的使用帮助请参照官网。
我们通过一个简单的例子,来展现ts中接口的使用。对于原先的javascript,如果你有写插件的经验,你通常会见过如下代码
function setConfig(config)
{
var defaults = {
color:'red',
num:2,
length:15
}
var opts = $.extend(true,defaults,config)
}
提供一些插件的默认选项。然后通过合并选项,确认插件应用的配置项。然后配置项是一个object对象。我无法限制用户到底给我传递了什么,或者用户根本不知道传递什么。这个时候我们就可以利用typescript
的interface
接口了。
interface MyConfig
{
color:string,
num:number,
length:15
}
以上代码定义了一个接口类型MyConfig
,修改最上面的代码如下。
function setConfig(config:MyConfig) : void
{
var defaults:MyConfig = {
color:'red',
num:2,
length:15
}
//--合并选项
}
这样就能规定,用户必须传递我如上规定的这种类型,才可以正常工作。当然,参数是不固定的,我们只需要修改接口的定义如下即可:
interface MyConfig
{
color?:string,
num?:number,
length?:15
}
这样用户可以随意传递这种定义的接口内的任意属性。
当然,这只是接口的一种最简单的使用方式。想要获取更多,请前往官网。
在JavaScript中,我们经常会声明一个空对象,然后再给这个属性进行赋值。但是这个操作放在TypeScript中是会发生报错的:
let a = {};
a.b = 1;
// 终端编译报错:TS2339: Property 'b' does not exist on type '{}'.
// 编辑器报错:[ts] 类型“{}”上不存在属性“b”。
这是因为TypeScript不允许增加没有声明的属性。
因此,我们有两个办法来解决这个报错:
1 在对象中增加属性定义(推荐)。具体方式为:let a = {b: void 0};。这个方法能够从根本上解决当前问题,也能够避免对象被随意赋值的问题。
2 给a对象增加any属性(应急)。具体方式为:let a: any = {};。这个方法能够让TypeScript类型检查时忽略这个对象,从而编译通过不报错。这个方法适用于大量旧代码改造的情况。
这对于工具函数的导出,就存在问题。
typescript 内,如果要引用第三方库,因为不可能每一种库都有强制类型,所以会IDE提示报错,因为他根本不认识。会报错。为了让typescrpt认识这种库,所以就有了.d.ts
这种描述文件。正确引入该文件之后,就可以让typescript认识这个库了。进而会有语法提示,函数参数说明等功能。但是第三方库的描述文件不可能由我们开发人员去写,因此typescript经历了3个过程(从 DefinitelyTyped 到 typings。最后是 @types),直到typescript2.0
,@types
方式才确定下来。@types
方式可以使得typescript编译器自动识别node_modules
目录下的.d.ts
描述文件。以引入jquery库为例。只需在项目目录下运行
npm install @types/jquery --save
即可在node_modules
目录下自动生成@types/jquery文件夹:
这样我们就可以在代码中使用$了。
import $ from 'jquery'
//--
$.extend;
//--
};;
采用@types
npm install --save-dev @types/activex-excel
不断更新中…