原文地址: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。 Angular 2 是如今一个很火的编程语言,尽管开发者能够继续使用 Javascript 去开发,可是不少教程和例子都是用 Typescript 写的。随着 Angular 2 社区的扩展,天然愈来愈多的人会选择 Typescript. (译者注:这篇教程写自2016年,如今react,vue,babel都支持了 Typescript。这篇文章中的 Typescript 的基础概念对如今仍是适用的)git
npm install -g typescript
复制代码
在命令提示行中输入 tsc -v
能够检查 Typescript 是否被安装:程序员
tsc -v
Version 1.8.10
复制代码
Typescript 是由微软支持和维护的一个开源项目,因此微软的Visual Studio原生支持 Typescript。现在,有不少编辑器和IDE均可以原生的或者经过插件来支持 Typescript 的语法提示,自动补充建议,错误提醒甚至编译 Typescript。github
Typescript通常会写在.ts(或者.tsx对于jsx来讲)文件中,.ts文件不能直接用在浏览器中,须要先被转义成.js文件。Typescript能够经过如下几种方式编译:
tsc
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的信息在这个文档中。
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'. 复制代码
如下是一些最经常使用的数据类型:
官方文档罗列了全部Typescript包含的数据类型
接口被用来检查一个对象(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的官方文档
咱们一样也关注到最新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类的内容,请阅读官方文档
泛型是一个模板,它容许函数接受不一样类型的入参。相较于使用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文档中包含了两个高级的例子,包含了泛型类,以及与接口结合使用的方法。若是想阅读更多,请点击这里。
另外一个关于大型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模块的内容能够点击这里。
ts声明文件常常是手写的,可是一些库也有其它人已经写好的.d.ts文件。DefinitelyTyped是最大的公共资源仓库,包含了不少的文件可引用。另外一个著名的用node模块管理Typescript定义的叫Typings.
更多关于声明文件的内容能够看这里。
刚开始,阅读官方文档的内容可能有点多,可是带来的收益是巨大的。咱们的教程只是作一个入门的介绍,咱们不可能覆盖全部文档的内容。下面是咱们没有包含到的内容:
但愿这篇入门教程能给你带来帮助。 若是你有任何想法或者想使用Typescript在你的项目里,能够在下面留言。