【译】30 分钟入门 Typescript

原文地址:learn-typescript-in-30-minutesjavascript

原文做者:Danny Markovhtml

译者:Jerry前端

译文首发地址:jerryjiao.life/vue

今天咱们来学习 Typescript,一门被设计用来开发大型和复杂 apps 的语言。相较于松散的,弱类型的 Javascript , Typescript 继承了不少其它高级语言( c# , java )的概念,进而更加的规范。java

这篇入门针对于有必定的 Javascript 基础而且打算学习 Typescript 的人。咱们覆盖了不少基础和关键的概念,并辅以不少例子来帮助你理解这门语言。让咱们开始吧。node

(译者说明:这篇文章不算新,16年末的文章。可是我浏览了其它一些英文的 Typescript 入门的文章,感受仍是这篇文章覆盖的内容全面一些,更适合初学者。并且一些基础内容,是变化不大的,因此选择了这篇文章。翻译这篇文章的时候,一些2.0新特性的简述的内容没有翻译,由于已是发布过的了。)react

使用 Typescript 的好处

https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2019/1/25/16882f003afbb612~tplv-t2oaga2asx-image.image
Javascript 已经很好了,我真的须要学习 Typescript 么?严格意义上讲,你不须要经过学习 Typescript 去变成一个好的程序员,大部分人没有使用 Typescript 依然很优秀。固然,使用 Typescript 编程也有一些显而易见的好处:

  • 由于 Typescript 类型是固定的,用 Typescript 写的代码更加容易把控,也更易于调试。
  • 得益于模块,命名空间和更好的面向对象编程的支持,使得 Typescript 更容易去构建大型和复杂的 apps。
  • 由于 Typescript 有编译成 Javascript 的过程,使其能够在项目上线运行和发生错误以前能够捕获到不一样类型的错误。
  • Angular2 是用 Typescript 写的,它也推荐开发人员使用 Typescript 去开发项目

最后也很主要的一点,对于大部分人去学 Typescript。 Angular 2 是如今一个很火的编程语言,尽管开发者能够继续使用 Javascript 去开发,可是不少教程和例子都是用 Typescript 写的。随着 Angular 2 社区的扩展,天然愈来愈多的人会选择 Typescript. (译者注:这篇教程写自2016年,如今react,vue,babel都支持了 Typescript。这篇文章中的 Typescript 的基础概念对如今仍是适用的)git

https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2019/1/25/16882f003ae58ff3~tplv-t2oaga2asx-image.image
(近期 Typescript 普及度增长,数据来自谷歌趋势)

Typescript的安装

https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2019/1/25/16882f003b536415~tplv-t2oaga2asx-image.image
最简单安装 Typescript 的方法是经过 npm 工具,使用如下的命令咱们能够全局安装 Typescript,能够在咱们的项目中使用 Typescript 转换器:

npm install -g typescript
复制代码

在命令提示行中输入 tsc -v 能够检查 Typescript 是否被安装:程序员

tsc -v
Version 1.8.10
复制代码

支持 Typescript 的编辑器

https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2019/1/25/16882f003b80163a~tplv-t2oaga2asx-image.image

Typescript 是由微软支持和维护的一个开源项目,因此微软的Visual Studio原生支持 Typescript。现在,有不少编辑器和IDE均可以原生的或者经过插件来支持 Typescript 的语法提示,自动补充建议,错误提醒甚至编译 Typescript。github

Typescript的编译

https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2019/1/25/16882f003b9fb43e~tplv-t2oaga2asx-image.image

Typescript通常会写在.ts(或者.tsx对于jsx来讲)文件中,.ts文件不能直接用在浏览器中,须要先被转义成.js文件。Typescript能够经过如下几种方式编译:

  • 经过前文关注过的,命令行工具 tsc
  • 直接在Visual Studio中或者其它IDE中
  • 使用一些前端打包工具例如 gulp

咱们发现第一种方式更加简单也对初学者更友好,因此在这篇文章中咱们将会使用第一种方式。

下面的命令将会转换main.ts这个Typescript文件为main.js.若是main.js存在,它将会被覆盖。

tsc main.ts
复制代码

咱们也能够罗列多个文件或者使用通配符去编译:

# 将会编译出分离的Javascript文件: main.js worker.js
tsc main.ts worker.ts

# 编译全部的在这个目录下的全部ts文件,不能递归执行。
tsc *.ts
复制代码

咱们也可使用--watch来自动编译Typescript文件在Typescript文件改变时:

# 初始化一个watcher的进程来保持main.js为最新
tsc main.ts --watch
复制代码

更多Typescript的用户也使用建立 tsconfig.json, 包含不一样的编译的配置。配置文件对一个包含不少的.ts文件的项目编译很便利,由于它定义了自动化的流程。你能够得到更多包含tsconfig.json的信息在这个文档中。

静态类型

https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2019/1/25/16882f003c68615f~tplv-t2oaga2asx-image.image

Typescript一个很是明显的特征就是支持静态的类型。这就意味着,在声明变量的时候要同时声明变量的类型,编译器会保证变量不会被赋值为错误的类型。一旦变量的类型被声明,他们将会从你的代码中作到自动的推测。

这里是一个例子,任何的变量,函数以及返回值在一开始都要被声明类型:

var burger: string = 'hamburger',  //String
 calories:number = 300, // Numberic
 tasty: boolean = true; //Boolean

 // 天然地,你也能够 省略变量的声明
 // var burger = 'hamburger'

 // 函数通常返回一个string或数字
 // 若是函数为void类型,它将不会返回什么东西

 function speak(food:string, energy:number):void {
    console.log("Our " + food + " has " + energy + " calories.");
 }
 speak(burger, calories);
复制代码

正由于Typescript将会被转为js, 一些没有语义和类型的字符,将会被移除:

// 一个Typescript转为js的例子
var burger = 'hamburger',
calories = 300,
tasty = true;

function speak(food, energy) {
console.log("Our " + food + " has " + energy + " calories.");
}

speak(burger, calories);
复制代码

固然,若是你的代码不符合规则,tsc命令行工具将会警告咱们错误在哪,好比:

// 当变量被声明为boolean,但被赋值为string的时候
 var tasty: boolean = "I haven't tried it yet";
复制代码
main.ts(1,5): error TS2322: Type 'string' is not assignable to type 'boolean'.
复制代码

若是咱们写错函数的入参类型,tsc也会提示:

function speak(food: string, energy: number): void{
console.log("Our " + food + " has " + energy + " calories.");
}

// 函数入参的类型错误
speak("tripple cheesburger", "a ton of");
复制代码
main.ts(5,30): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'.
复制代码

如下是一些最经常使用的数据类型:

  • Number - 全部的数字类型均可以被声明为number 类型,它们不会被区分为int,float或者其它
  • String - 字符串类型,和Javascript字符串类型同样,能够被单引号和双引号包括
  • Boolean - true或者false,若是使用0或1将会报错
  • Any - 这种变量它能够被赋值为各类类型,不管是string,number,或者其它各类类型。
  • Arrays - 有两种可能的语法:my_arr:number[]; 或者 my_arr: Array
  • Void - 运用在不返回任何值的函数

官方文档罗列了全部Typescript包含的数据类型

接口

https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2019/1/25/16882f00b25683e0~tplv-t2oaga2asx-image.image

接口被用来检查一个对象(object)是否符合固定的结构。经过定义接口,咱们能够命名一个特殊的变量的组合,确保它们的是固定的。当转译为Javascript的时候,接口将会消失-接口的目标就是在开发过程当中给予帮助。

下面的例子,咱们定义一个简单的接口对函数的入参进行类型检查:

// 这里咱们定义了一个 Food的接口,包含它的属性和其类型
interface Food {
    name: string;
    calories:number;
}

// 咱们能够告诉函数咱们但愿的入参,来符合Food这个接口
// 这种方式能够保证属性永远的可用
function speak(food: Food): void {
    console.log("Our " + food.name + " has " + food.calories + " calories.");
}

// 咱们定义一个对象,它知足Food接口规定的属性
// 注意 这个类型将被自动的推测

var ice_cream = {
    name: "ice cream",
    calories: 200
}

speak(ice_cream);

复制代码

属性的顺序不重要,咱们要保证属性名字和类型的正确。若是少了某些属性,或者写了错误的类型,或者名字不一样,ts的编译器都会警告咱们。

interface Food {
name: string;
calories: number;
}

function speak(food: Food): void{
console.log("Our " + food.name + " has " + food.calories + " grams.");
}

// 咱们写了一个错误的属性名 nmae
var ice_cream = {
nmae: "ice cream",
calories: 200
}

speak(ice_cream);
复制代码

报错信息:

main.ts(16,7): error TS2345: Argument of type '{ nmae: string; calories: number; } is not assignable to parameter of type 'Food'. Property 'name' is missing in type '{ nmae: string; calories: number; }'. 复制代码

这是一个面对初学者的教程,若是你想得到更多关于interface的信息,请访问ts的官方文档

类型和面向对象编程

https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2019/1/25/16882f00a890f488~tplv-t2oaga2asx-image.image
当构建一个大型的apps的时候,大多数开发者喜欢面向对象编程,尤为是在java,c#这样的编程语言里。Typescript提供了类的系统,它很像Java,c#这样的语言。包含继承,抽象类,接口实现,setters/getters和其它。

咱们一样也关注到最新Javascript的更新(ECMAScript 2015),Javascript原生对class提供了支持。Typescript和Javascript对类的应用很类似,可是有不一样的地方。Typescript更严格一些。

延续以前food例子的风格,下面是一个简单的Typescript类的例子:

class Menu {
// 类中的属性:
// 默认的,它们是public的,也能够是private 或者 protected
items: Array<string>; // 在菜单中的项目,一个strings类型的数组
pages: number; // 菜单有多少页面,一个数字

// 构造函数
constructor(item_list: Array<string>, total_pages: number) {
// 这里的关键词是强制的
this.items = item_list;
this.pages = total_pages;
}

// 方法
list(): void {
console.log("Our menu for today:");
for(var i=0; i<this.items.length; i++) {
console.log(this.items[i]);
}
}

}

// 建立一个新的‘菜单’类实例
var sundayMenu = new Menu(["pancakes","waffles","orange juice"], 1);

// 执行list方法
sundayMenu.list();
复制代码

熟悉java或c#的程序员对这种语法应该感受很熟悉,下面是继承的例子:

class HappyMeal extends Menu {
// 父类属性将会被继承
// 须要定义一个新的构造函数

constructor(item_list: Array<string>, total_pages: number) {
// 在这个例子中,咱们但愿和父类有一样的构造函数
// 为了更方便额度复制父类的构造函数,这里使用了super函数-引用了父类的构造函数
super(item_list, total_pages);
}

// 和属性同样,父类函数也会被继承
// 固然咱们也能够重写list()函数覆盖父类中的方法
list(): void{
console.log("Our special menu for children:");
for(var i=0; i<this.items.length; i++) {
console.log(this.items[i]);
}

}
}

// Create a new instance of the HappyMeal class.
var menu_for_children = new HappyMeal(["candy","drink","toy"], 1);

// This time the log message will begin with the special introduction.
menu_for_children.list();


复制代码

若是想更深刻的了解Typescript类的内容,请阅读官方文档

泛型

https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2019/1/25/16882f00b4f8e013~tplv-t2oaga2asx-image.image

泛型是一个模板,它容许函数接受不一样类型的入参。相较于使用any这个类型,用泛型建立一个复用的组件会更好,由于泛型保留了进出变量的类型。

下面是一个简单的例子,这个函数会接收一个参数而且返回包含这个参数的数组。

// 在函数后面的<T>标识符表示了一个函数为泛型函数
// 当咱们执行函数的时候,每个T的实例将会被替换为真实提供的类型

// 接收一个入参,类型为T
// 返回一个数组,类型为T

function genericFunc<T>(argument: T): T[] {
var arrayOfT: T[] = []; //建立一个T类型的空数组
arrayOfT.push(argument); // 入参添加进这个数组中
return arrayOfT;
}

var arrayFromString = genericFunc<string>("beep");
console.log(arrayFromString[0]); // "beep"
console.log(typeof arrayFromString[0]) // String

var arrayFromNumber = genericFunc(42);
console.log(arrayFromNumber[0]); // 42
console.log(typeof arrayFromNumber[0]) // number
复制代码

第一次咱们执行函数的时候,咱们不须要手动的传入的参数的类型(string),由于编译器能够识别到传递了什么参数,并自动决定什么类型最适合它;就像在第二个调用中那样,虽然这不是必须的,可是仍是推荐每次都指定泛型的类型,由于编译器可能在复杂的情景下推测出错误的类型。

Typescript文档中包含了两个高级的例子,包含了泛型类,以及与接口结合使用的方法。若是想阅读更多,请点击这里

模块

https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2019/1/25/16882f00b66d14f8~tplv-t2oaga2asx-image.image

另外一个关于大型apps的概念是模块化。若是你的代码能够划分为许多小的,可重复使用的模块,将会使你的项目更加条理和易于理解的。比一个有10000行的文件好不少。

Typescript引入了一种语法去输出和引入模块,可是没法掌控文件间的实际链接。为了能使Typescript文件使用第三方的库,例如用在浏览器apps的require.js和Node.js的CommmonJs.让咱们看一个简单的例子--Typescript模块和require.js:

咱们有两个文件,一个输出函数,另外一个引入它而且执行它:

expoter.ts

var sayHi = function():void {
    console.log("Hello!");    
}

export = sayHi;
复制代码

importer.ts

import sayHi = require('./exporter');
sayHi();
复制代码

如今咱们须要下载require.js并用 <script> 标签引入到文件中 -

这里会告诉你怎么作。最后一个是转换这两个.ts文件。在转换的时候输入另外一个参数,告诉编译器咱们想使用AMD的方式引用,而不是 CommonJS 的方式

tsc --module amd *.ts
复制代码

若是你想了解更多Typescript模块的内容能够点击这里

声明文件

https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2019/1/25/16882f05a47f2e54~tplv-t2oaga2asx-image.image
当咱们想使用以前Javascript中常用的库,咱们须要去使用声明文件去使得这些库适用于ts。一个声明文件的扩展名为.d.ts,包含了关于库的信息和API。

ts声明文件常常是手写的,可是一些库也有其它人已经写好的.d.ts文件。DefinitelyTyped是最大的公共资源仓库,包含了不少的文件可引用。另外一个著名的用node模块管理Typescript定义的叫Typings.

更多关于声明文件的内容能够看这里

更多内容

刚开始,阅读官方文档的内容可能有点多,可是带来的收益是巨大的。咱们的教程只是作一个入门的介绍,咱们不可能覆盖全部文档的内容。下面是咱们没有包含到的内容:

最后

但愿这篇入门教程能给你带来帮助。 若是你有任何想法或者想使用Typescript在你的项目里,能够在下面留言。

相关文章
相关标签/搜索