摘要:訪問越界的元素,使用聯合類型替代。構造函數不能聲明返回類型。在子類中運行構造函數式繼承實現對父類的構造函數繼承。的核心原則之一是對值所具有的進行類型檢查。外部模塊則稱之為模塊語法通過關鍵字,將模塊的方法屬性暴露出來。
介紹
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文件。然后,在頁面上通過