摘要:访问越界的元素,使用联合类型替代。构造函数不能声明返回类型。在子类中运行构造函数式继承实现对父类的构造函数继承。的核心原则之一是对值所具有的进行类型检查。外部模块则称之为模块语法通过关键字,将模块的方法属性暴露出来。
介绍
TypeScript是JavaScript的超集,为JavaScript的生态增加了类型机制,并最终将代码编译为纯粹的JavaScirpt代码。
编译浏览器加载文件编译
注意,编译的TypeScript文件需要放在编译文件之前
自动化构架工具
1:fis
fis插件:fis-parser-typescript
var fis = require("fis3"); var typescirpt = require("fis3-parser-typescript"); fis.match("**.ts", { parser: fis.plugin("typescript"), rExt: ".js" });
2: gulp
使用gulp插件:gulp-typescript
var gulp = require("gulp"); var ts = require("gulp-typescript"); gulp.task("compileTs", function () { gulp.src("**.ts") .pipe(ts()) .pipe(gulp.dest("dist")); }); gulp.task("default", ["compileTs"]);基础类型
typescript囊括了所有JavaScript基本类型
基本类型number 数字类型
string 字符串类型
boolean 布尔类型
any 任意一种
数组定义数组
两部分:前面一部分表示数组成员的类型,后面一部分表示告知是一个数组。
let arr:number[] = [12, 23]; let colors:any[] = [12, "cyan", "pink"]; // 数组任意类型 let list:Array元组= [1, 2, 3]; // 数组泛型
Tuple
元组类型允许表示一个已知元素数据和类型的数组,各元素的类型不必相同。
let x: [string, number] = ["cyan", 10];
访问越界的元素,使用联合类型替代。
枚举定义:enum colors { red, green, blue }
表义一种可以一一列举的数据
特点:
通过索引值访问定的数据。
通过定义的数据访问索引值。
对枚举类型的数据添加起始索引值。
enum color { red = 10, // 默认索引值从0 开始, 可以指定索引值 green, blue } // 编译之后: Object {10: "red", 11: "green", 12: "blue", red: 10, green: 11, blue: 12}空值
void 类型 像是 与 any 类型相反,它表示没有任何类型。 当一个函数没有返回值时, 要指定 void 类型。
void 类型 只能赋值: undefiend 和 null。
let unvoid: void = null; let unvoid1: void = undefined;undefiend和null
undefeind和null两者有各自的类型: undefined和null。 和void相似。
let u: undefined = undefined; let n: null = null;
默认情况下null 和undefined 是所有类型的子类型。
可以把null 和undefined赋值给number类型的变量。
类型断言,类似其它语言里的类型转换。但是不进行特殊的数据检查和解构。 没有运行时的影响,只是在编译阶段其作用。
尖括号<>语法
let someValue: any = "colors"; let strlength: number = (变量声明 let&constsomeValue).length; console.log(strlength);
const 是对let的一个增强,能阻止对一个变量再次赋值。
let 和 const 的区别:
所有变量除了计划要去修改的都应该使用const。
基本原则就是如果一个变量不需要对它写入,那么其它使用这些代码的人也不能够写入它们。
使用const可以更容易推测数据的流动性。
解构数组
不需要指定类型
let input = [1, 2]; let [fisrt, second] = input; console.log(fisrt, second); // 1 ,2
对象结构
let o = { a: "foo", b: 12, c: "bar" } let {a, b} = o; console.log( a, b );函数
TypeScript函数可以创建有名字的函数和匿名函数
TypeScript函数执行返回值需要定义数据类型,如果没有结果则要定义为void。
TypeScript函数,参数需要定义类型,在调用的时候,传递的参数一定要跟定义时的参数个数一样。否则编译报错。
function add (a:number, b:number):number { return a + b; } let sum = add(10, 20); console.log( sum );
// 定义void返回值 setProperty(); function setProperty (): void { console.log("success"); }可选参数和默认参数
在TypeScript中可以在参数名旁边使用 ? 实现可选参数
function count (str1: string, str2?: string): string { return str1 + "--" + str2; } let reslut = count("xixi"); console.log( reslut );剩余参数
剩余参数会被当作个数不限的可选参数。可以一个都没有,同样也可以有任意个。
语法:...nameProperty
function builName (numa1: string, ...restOfName: string[]) { // 剩余参数保存在数组中 }Class
在TypeScript中,可以通过Class来定义一个类。在编译之后,会编译成JavaScript一个闭包函数类。
语法: class className {}
成员方法,成员属性在类中添加的属性会编译到构造函数中,该属性如果不赋值,则不会被编译.
在类中添加的方法会编译到构造函数的Prototype上。
class Price { price: number = 10; fn( num: number ): string { return num * 2; } }
编译之后的结果:
//Compiled TypeScript var Price = (function () { function Price() { this.price = 10; } Price.prototype.fn = function (num) { return num * 2; }; return Price; })();静态属性,静态方法
静态属性:通过static关键字定义,定义的该属性,在 类中访问不到, 因为定义在类上。
静态方法:通过static关键字定义,定义的该方法,在类中是访问不到(不能通过this访问),因为该方法定义在类上。
class Person { static name: string = "time"; static fn(num: number): void { console.log("success"); } } let p1: Peson = new Person(); // 实例化
编译之后:
var Person = (function () { function Person() { } Person.fn = function (num) { console.log("success"); console.log(Peson.name); }; Person.name = "time"; return Person; })(); var p1 = new Person();构造函数
在实例化的时候被调用
构造函数中定义的语句会编译到JavaScript的构造函数中。
构造函数不能声明返回类型。
类定义的属性(赋值的属性)会被编译到JavaScirpt的构造函数中。
class Book { name: string; page: number = 400; constructor(bookName: string) { this.name = bookName; console.log(bookName); } } let p1: Book = new Book("庄子");
编译之后:
var Book = (function () { function Book(bookName) { this.page = 400; this.name = bookName; console.log(bookName); } return Book; })(); var p1 = new Book("庄子");继承
语法:子类 extends 父类
class Base { press: string = "one"; } class Book extends Base { name: string = "老子"; sayName(): string { return this.name; } } let b: Book = new Book(); let bookname = b.sayName(); console.log(bookname);
编译之后:
通过的是混合式继承
var __extends = this.__extends || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; function __() { this.constructor = d; } __.prototype = b.prototype; d.prototype = new __(); }; var Base = (function () { function Base() { this.press = "one"; } return Base; })(); var Book = (function (_super) { __extends(Book, _super); function Book() { _super.apply(this, arguments); this.name = "老子"; } Book.prototype.sayName = function () { return this.name; }; return Book; })(Base); var b = new Book(); var bookname = b.sayName(); console.log(bookname);
——extends(); 方法
var __extends = this.__extends || function (d, b) { // b 父类 for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; function __() { this.constructor = d; } __.prototype = b.prototype; d.prototype = new __(); };
目的, 实现只继承 父类的原型对象。 从原型对象入手
1,function __() {}创建一个空函数, 目的:空函数进行中转,把父类的模板屏蔽掉, 父类的原型取到。
2,__.prototype = b.prototype实现空函数的原型对象 和 超类的原型对象转换
3,d.prototype = new __()原型继承
使用for-in循环,子类继承父类的静态属性或方法。(通过一个函数中转,实现,只实例化一次,且继承了一次父类的原型对象)
通过寄生类继承父类原型上的属性或方法。
在子类中运行构造函数式继承实现对父类的构造函数继承。
super()
在包含constructor函数的子类中必须调用super().它会执行基类的构造方法。
传递给super()方法就是实现构造函数继承属性
子类构造函数中添加属性。
继承父类构造函数中的属性,如果子类定义构造函数就必须继承。
class Base { press: string = "one"; name: string; constructor ( bookName: string ) { this.name = bookName; } } class Book extends Base { price: number; // name: string = "老子"; constructor(bookName: string, price: number) { // 父类继承属性 super(bookName); // 会执行父类的 constructor this.price = price; } sayName(): string { return this.name; } } let b: Book = new Book("老子", 40); let bookname = b.sayName(); console.log(bookname);接口
在TypeScript中,接口的作用:为这些类型命名和为你的代码或第三方代码定义契约。
TypeScript的核心原则之一是:对值所具有的shape进行类型检查。
定义一种数据格式,来约束变量的类型。
接口中定义的每个接口,都可以当作一种类型来使用。
可选实现成员,可以在后面添加?.
语法:interface names {};
接口定义对象// 定义接口 interface Person { name: string; age: number; sex: string; hobby?: any; } // 使用接口 function getName (person: Person): string { return person.name; } // 实现接口 var n: string = getName({ name: "one", age: 23, sex: "nv" }); console.log(n);接口函数
语法:interface name {}
定义函数格式.通过()来定义参数个数,并声明函数返回值类型。
作用:限制了定义该函数类型的规范。
// 定义抽象类 interface Add { (num1: number, num2: number): number; } // 使用接口 let fn:Add; // 实现接口 fn = function ( num1: number, num2: number ): number { return num1 + num2; } var reslut: number = fn(10 , 20); console.log(reslut);类的接口定义
语法:
interface className { key: type; fn(arg: type): type; }
实现接口:
class Times implements Base {}
作用:保证代码的安全性
"use strict"; // 时间接口 interface Base { current: string; getCurrentDate(): string; } // 使用接口 class Times implements Base { current: string; constructor( d: string ){ this.current = d; } getCurrentDate (): string { return this.current; } } let d: Times = new Times(new Date().toString()); console.log(d);模块
在TypeScript1.5中:内部模块 是说所的命名空间。 外部模块则称之为模块
语法:
module name {}
通过 export关键字, 将模块的方法属性暴露出来。
在模块的外部访问模块,需要通过模块名称,点语法调用模块内部暴露的接口
"use strict"; // 定义模块 module startModuel { let info: string = "colors"; // 暴露一个class export class Satrt { name: string; constructor(name: string) { this.name = name; } getName(): string { return this.name; } } } // 实例化模块中暴露的接口 let satr:startModuel.Satrt = new startModuel.Satrt("cyan"); console.log( satr ); console.log(satr.getName());
模块在其自身的作用域里执行,而不是在全局作用域里。
一个模块里的比那两,函数,类等等在模块外部是不可见的,需要通过export形式向外暴露。
如果一个模块想使用其它模块导出的变量,函数,类,接口等。需要使用import形成引入。
模块是自声明的。两个模块之间的关系是通过在文件级别上使用imports和 exports 建立联系的。
导出导出声明
export interface StringValidator { isAcce(s: string): boolean; } export const numberRegExp = /^[0-9]+$/;
导出语句
export class ZipCode implements StringValidator { isAcce(s: string) { return s.length === 5 && numberRegExp.test(s); } } // 导出语句 export { ZipCode }导入
使用关键字:import 来导入其它模块中的导出内容
import { ZipCode } form "./ZipCode"; let myValid = new ZipCode();
// 对导入的内容重新命名 import {ZipCode as ZVC } form ""./ZipCode; let myValid = new ZVC();
默认导出
每个模快都有一个defalut导出。 默认导出使用default 关键字标记。
例如:JQuery的类库有一个默认导出JQuery或$.
let $:jQuery; export default $;
import $ from "JQuery";模块路径解析
TypeScript存在两种路径解析方式: Node和Classic(原本TypeScirpt路径解析规则,为了向后兼容)
TypeScript是模范Node运行时解析策略来编译阶段定义模块文件。
TypeScript在Node解析逻辑基础上增加了TypeScript源文件的扩展名(.ts,.tsx,.d.ts).
命名空间是位于全局命名空间下的一个普通的带有名字的JavaScript对象
使用关键字:namespace
namescope Valiation { export interface StringValidator { isAcce(s: string): boolean; } const lettesRegExp = /^[A-Za-z]+$/; }
多文件的命名空间
不同的文件,但是仍是同一个命名空间,并且在使用的时候,就如同他们在一个文件中定义的一样。 因为不同文件之间存在依赖关系,所以加入了引用标签来告知编译器文件之间的关联。
namescope Valiation { export interface StringValidator { isAcce(s: string): boolean; } } namescope Valiation { const lettesRegExp = /^[A-Za-z]+$/; expots class LetterOnly implements StringValidator { isAcce(s: string): boolean { return s.length && lettesRegExp.test(s); } } }
// 测试 ////// let strings = ["Hello", "98052"]; let validators: { [s: string]: Validation.StringValidator; } = {}; validators["ZIP code"] = new Validation.ZipCodeValidator(); validators["Letters only"] = new Validation.LettersOnlyValidator(); strings.forEach(s => { for (let name in validators) { console.log(""" + s + "" " + (validators[name].isAcce(s) ? " matches " : " does not match ") + name); } });
编译方式:
把所有输入的文件编译一个输出文件,需要使用--outFile标记
tsc --outFile sample.js Test.ts
变异其会根据源码中引用标签自动的对输出进行排序。
可以多带带指定每个文件
tsc --outFile sample.js Validation.ts LettersOnlyValidator.ts ZipCodeValidator.ts Test.ts
可以编译成每一个文件(默认方式),每个源文件都会对应生成一个JavaScript文件。然后,在页面上通过