與JS相似部分,本文不作說明(運算符、條件語句、循環語句、函數、基本類型等)javascript
TypeScript
的設計目的應該是解決JavaScript的痛點
:弱類型和沒有命名空間,致使很難模塊化,不適合開發大型程序。另外它還提供了一些語法糖來幫助你們更方便地實踐面向對象的編程。前端
TypeScript
並無拋棄JavaScript
的語法另起爐竈,而是作成了JavaScript的超集,這樣任何合法的JavaScript的語句在TypeScript下都是合法的,也就是說學習成本很低java
語法糖:TypeScript
能夠實現類,接口,枚舉,泛型,方法重載等,用簡潔的語法豐富了JavaScript
的使用。node
類型檢查:谷歌的Flow
也能夠作到ajax
ES6用類Class
(語法糖)也挺好用的啦......typescript
TypeScript
TypeScript
實例//var [變量名] : [類型] = 值;
const hello : string = "Hello World!"
console.log(hello)
複製代碼
TypeScript
安裝【即在cmd中將ts編譯成js的命令】npm install -g typescript
複製代碼
//如下是查看版本號
$ tsc -v
Version 3.2.2
複製代碼
var message:string = "Hello World"
console.log(message)
複製代碼
tsc
命令將 TypeScript 轉換爲 JavaScript 代碼:tsc test.ts
複製代碼
var message = "Hello World";
console.log(message);
複製代碼
$ node test.js
Hello World
複製代碼
TypeScript 轉換爲 JavaScript 過程以下圖: npm
咱們能夠同時編譯多個 ts 文件:編程
tsc file1.ts, file2.ts, file3.ts
複製代碼
1. --help顯示幫助信息
2. --module載入擴展模塊
3. --target設置 ECMA 版本
4. --declaration額外生成一個 .d.ts 擴展名的文件。
tsc ts-hw.ts --declaration生成 ts-hw.d.ts、ts-hw.js 兩個文件。
5. --removeComments刪除文件的註釋
6. --out編譯多個文件併合併到一個輸出的文件
7. --sourcemap生成一個 sourcemap (.map) 文件。sourcemap 是一個存儲源代碼與編譯代碼對應位置映射的信息文件。
8. --module noImplicitAny在表達式和聲明上有隱含的 any 類型時報錯
9. --watch在監視模式下運行編譯器。會監視輸出文件,在它們改變時從新編譯。
複製代碼
TypeScript
元祖&聯合類型var val:string|number
val = 12
console.log("數字爲 "+ val)
val = "Runoob"
console.log("字符串爲 " + val)
複製代碼
function disp(name:string|string[]) {
if(typeof name == "string") {
console.log(name)
} else {
var i;
for(i = 0;i<name.length;i++) {
console.log(name[i])
}
}
}
複製代碼
var arr:number[]|string[]
TypeScript
接口接口是一系列抽象方法的聲明,是一些方法特徵的集合,這些方法都應該是抽象的,須要由具體的類去實現json
/** TypeScript 接口定義以下 interface interface_name { } 如下實例中,咱們定義了一個接口 IPerson, 接着定義了一個類型爲IPerson變量 customer customer 實現了接口 IPerson 的屬性和方法。 注意接口不能轉換爲 JavaScript。 它只是 TypeScript 的一部分。 */
interface IPerson {
firstName:string,
lastName:string,
sayHi: ()=>string
}
var customer:IPerson = {
firstName:"Tom",
lastName:"Hanks",
sayHi: ():string =>{return "Hi there"}
}
console.log("Customer 對象 ")
console.log(customer.firstName)
console.log(customer.lastName)
console.log(customer.sayHi())
複製代碼
interface RunOptions {
program:string;
commandline:string[]|string|(()=>string);
}
// commandline 是字符串
var options:RunOptions = {program:"test1",commandline:"Hello"};
console.log(options.commandline)
// commandline 是字符串數組
options = {program:"test1",commandline:["Hello","World"]};
console.log(options.commandline[0]);
console.log(options.commandline[1]);
// commandline 是一個函數表達式
options = {program:"test1",commandline:()=>{return "**Hello World**";}};
var fn:any = options.commandline;
console.log(fn());
複製代碼
/** 接口中能夠將數組的索引值和元素設置爲不一樣類型, 索引值能夠是數字或字符串 */
interface namelist {
[index:number]:string
}
// 錯誤元素 1: 不是 string 類型
var list2:namelist = ["John",1,"Bran"]
interface ages {
[index:string]:number
}
var agelist:ages;
agelist["John"] = 15 // 正確
agelist[2] = "nine" // 錯誤
複製代碼
/** 接口繼承就是說接口能夠經過其餘接口來擴展本身。 Typescript 容許接口繼承多個接口。 繼承使用關鍵字 extends。 */
//單接口繼承語法格式:
Child_interface_name extends super_interface_name
//多接口繼承語法格式:
Child_interface_name extends super_interface1_name,
super_interface2_name,…,super_interfaceN_name
//單繼承實例
interface Person {
age:number
}
interface Musician extends Person {
instrument:string
}
var drummer = <Musician>{};
drummer.age = 27
drummer.instrument = "Drums"
console.log("年齡: "+drummer.age)
console.log("喜歡的樂器: "+drummer.instrument)
//多繼承實例
interface IParent1 {
v1:number
}
interface IParent2 {
v2:number
}
interface Child extends IParent1, IParent2 { }
var Iobj:Child = { v1:12, v2:23}
console.log("value 1: "+Iobj.v1+" value 2: "+Iobj.v2)
複製代碼
TypeScript
類類描述了所建立的對象共同的屬性和方法。後端
//語法:class class_name { }
class Person {}
//編譯成js就是:
var Person = /** @class */ (function () {
function Person() {
}
return Person;
}());
//建立類的數據成員
class Car {
engine:string; // 字段
constructor(engine:string) { // 構造函數
this.engine = engine
}
disp():void { // 方法
console.log("發動機爲 : "+this.engine)
}
}
//建立實例
var obj = new Car("Engine 1")
obj.disp()
複製代碼
子類除了不能繼承父類的私有成員(方法和屬性)和構造函數,其餘的均可以繼承。
TypeScript
一次只能繼承一個類,不支持繼承多個類,但TypeScript
支持多重繼承(A 繼承 B,B 繼承 C)。
//語法:class child_class_name extends parent_class_name
/** 下面實例中建立了 Shape 類, Circle 類繼承了 Shape 類, Circle 類能夠直接使用 Area 屬性 */
class Shape {
Area:number
constructor(a:number) {
this.Area = a
}
}
class Circle extends Shape {
disp():void {
console.log("圓的面積: "+this.Area)
}
}
var obj = new Circle(223);
obj.disp()
/** 類繼承後,子類能夠對父類的方法從新定義,這個過程稱之爲方法的重寫。 其中super關鍵字是對父類的直接引用,該關鍵字能夠引用父類的屬性和方法。 */
class PrinterClass {
doPrint():void {
console.log("父類的 doPrint() 方法。")
}
}
class StringPrinter extends PrinterClass {
doPrint():void {
super.doPrint() // 調用父類的函數
console.log("子類的 doPrint()方法。")
}
}
複製代碼
static
關鍵字
static
關鍵字用於定義類的數據成員(屬性和方法)爲靜態的,靜態成員能夠直接經過類名調用。
class StaticMem {
static num:number;
static disp():void {
console.log("num 值爲 "+ StaticMem.num)
}
}
StaticMem.num = 12 // 初始化靜態變量
StaticMem.disp() // 調用靜態方法
//上述代碼編譯成js就是
var StaticMem = /** @class */ (function () {
function StaticMem() {
}
StaticMem.disp = function () {
console.log("num 值爲 " + StaticMem.num);
};
return StaticMem;
}());
StaticMem.num = 12; // 初始化靜態變量
StaticMem.disp(); // 調用靜態方法
複製代碼
instanceof
運算符
instanceof
運算符用於判斷對象是不是指定的類型,若是是返回true
,不然返回false
class Person{ }
var obj = new Person()
var isPerson = obj instanceof Person;
console.log("obj 對象是 Person 類實例化來的嗎? " + isPerson);
複製代碼
可使用訪問控制符來保護對類、變量、方法和構造方法的訪問
/** public(默認) : 公有,能夠在任何地方被訪問。 protected : 受保護,能夠被其自身以及其子類和父類訪問。 private : 私有,只能被其定義所在的類訪問。 */
class Encapsulate {
str1:string = "hello"
private str2:string = "world"
}
var obj = new Encapsulate()
console.log(obj.str1) // 可訪問
console.log(obj.str2) // 編譯錯誤, str2 是私有的
複製代碼
類能夠實現接口,使用關鍵字
implements
interface ILoan {
interest:number
}
class AgriLoan implements ILoan {
interest:number
rebate:number
constructor(interest:number,rebate:number) {
this.interest = interest
this.rebate = rebate
}
}
var obj = new AgriLoan(10,1)
console.log("利潤爲 : "+obj.interest+",抽成爲 : "+obj.rebate )
複製代碼
TypeScript
對象JavaScript
對象沒啥區別/** 對象是包含一組鍵值對的實例。 值能夠是標量、函數、數組、對象等,以下實例 */
var object_name = {
key1: "value1", // 標量
key2: "value",
key3: function() {
// 函數
},
key4:["content1", "content2"] //集合
}
console.log(object_name.key1)
複製代碼
//假如咱們在 JavaScript 定義了一個對象:
var sites = {
site1:"Runoob",
site2:"Google"
};
//這時若是咱們想在對象中添加方法,能夠作如下修改:
sites.sayHello = function(){ return "hello";}
//若是在 TypeScript 中使用以上方式則會出現編譯錯誤,
//由於Typescript 中的對象必須是特定類型的實例。
--------------------------------------------------
//在typescript中得以下定義:
var sites = {
site1: "Runoob",
site2: "Google",
sayHello: function () { } // 類型模板
};
sites.sayHello = function () {
console.log("hello " + sites.site1);
};
sites.sayHello();
--------------------------------------------------
/** 鴨子類型(Duck Typing): 是動態類型的一種風格,是多態(polymorphism)的一種形式。 在這種風格中,一個對象有效的語義, 不是由繼承自特定的類或實現特定的接口, 而是由"當前方法和屬性的集合"決定。 能夠這樣表述: "當看到一隻鳥走起來像鴨子、游泳起來像鴨子、叫起來也像鴨子, 那麼這隻鳥就能夠被稱爲鴨子。" */
interface IPoint {
x:number
y:number
}
function addPoints(p1:IPoint,p2:IPoint):IPoint {
var x = p1.x + p2.x
var y = p1.y + p2.y
return {x:x,y:y}
}
// 正確
var newPoint = addPoints({x:3,y:4},{x:5,y:1})
// 錯誤
var newPoint2 = addPoints({x:1},{x:4,y:3})
複製代碼
TypeScript
命名空間TypeScript
中命名空間使用 namespace
來定義//語法以下:
namespace SomeNameSpaceName {
export interface ISomeInterfaceName { }
export class SomeClassName { }
}
/** 以上定義了一個命名空間 SomeNameSpaceName, 若是咱們須要在外部能夠調用 SomeNameSpaceName 中的類類和接口, 則須要在類和接口添加 export 關鍵字。 要在另一個命名空間調用語法格式爲: */
SomeNameSpaceName.SomeClassName;
/** 若是一個命名空間在一個單獨的 TypeScript 文件中, 則應使用三斜槓 /// 引用它,語法格式以下: */
/// <reference path = "SomeFileName.ts" />
複製代碼
IShape.ts 文件代碼:
namespace Drawing {
export interface IShape {
draw();
}
}
Circle.ts 文件代碼:
/// <reference path = "IShape.ts" />
namespace Drawing {
export class Circle implements IShape {
public draw() {
console.log("Circle is drawn");
}
}
}
Triangle.ts 文件代碼:
/// <reference path = "IShape.ts" />
namespace Drawing {
export class Triangle implements IShape {
public draw() {
console.log("Triangle is drawn");
}
}
}
TestShape.ts 文件代碼:
/// <reference path = "IShape.ts" />
/// <reference path = "Circle.ts" />
/// <reference path = "Triangle.ts" />
function drawAllShapes(shape:Drawing.IShape) {
shape.draw();
}
drawAllShapes(new Drawing.Circle());
drawAllShapes(new Drawing.Triangle());
使用 tsc 命令編譯以上代碼:
tsc --out app.js TestShape.ts
複製代碼
namespace namespace_name1 {
export namespace namespace_name2 {
export class class_name { }
}
}
//成員的訪問使用點號 . 來實現,以下實例:
//Invoice.ts 文件代碼:
namespace Runoob {
export namespace invoiceApp {
export class Invoice {
public calculateDiscount(price: number) {
return price * .40;
}
}
}
}
//InvoiceTest.ts 文件代碼:
/// <reference path = "Invoice.ts" />
var invoice = new Runoob.invoiceApp.Invoice();
console.log(invoice.calculateDiscount(500));
複製代碼
TypeScript
模塊TypeScript
模塊的設計理念是能夠更換的組織代碼。export
導出它們。相似地,咱們必須經過 import
導入其餘模塊導出的變量、函數、類等。import 和 export
創建的。JavaScript
模塊加載器是服務於 Node.js
的 CommonJS
和服務於 Web
應用的 Require.js
。SystemJs
和 Webpack
。模塊導出使用關鍵字 export 關鍵字,語法格式以下:
// 文件名 : SomeInterface.ts
export interface SomeInterface {
// 代碼部分
}
要在另一個文件使用該模塊就須要使用 import 關鍵字來導入:
import someInterfaceRef = require("./SomeInterface")
複製代碼
//IShape.ts 文件代碼:
/// <reference path = "IShape.ts" />
export interface IShape {
draw();
}
//Circle.ts 文件代碼:
import shape = require("./IShape");
export class Circle implements shape.IShape {
public draw() {
console.log("Cirlce is drawn (external module)");
}
}
//Triangle.ts 文件代碼:
import shape = require("./IShape");
export class Triangle implements shape.IShape {
public draw() {
console.log("Triangle is drawn (external module)");
}
}
//TestShape.ts 文件代碼:
import shape = require("./IShape");
import circle = require("./Circle");
import triangle = require("./Triangle");
function drawAllShapes(shapeToDraw: shape.IShape) {
shapeToDraw.draw();
}
drawAllShapes(new circle.Circle());
drawAllShapes(new triangle.Triangle());
複製代碼
TypeScript
聲明文件[declare
]TypeScript
做爲 JavaScript
的超集,在開發過程當中不可避免要引用其餘第三方的 JavaScript
的庫。TypeScript
諸如類型檢查等特性功能。JavaScript
庫和模塊信息的聲明文件。TypeScript
的各類特性來使用庫文件了。假如咱們想使用第三方庫,好比 jQuery,
咱們一般這樣獲取一個 id 是 foo 的元素:
$('#foo');
// 或
jQuery('#foo');
可是在 TypeScript 中,
咱們並不知道 $ 或 jQuery 是什麼東西:
jQuery('#foo');
// index.ts(1,1): error TS2304: Cannot find name 'jQuery'.
這時,咱們須要使用 declare 關鍵字來定義它的類型,
幫助 TypeScript 判斷咱們傳入的參數類型對不對:
declare var jQuery: (selector: string) => any;
jQuery('#foo');
declare 定義的類型只會用於編譯時的檢查,編譯結果中會被刪除。
上例的編譯結果是:
jQuery('#foo');
複製代碼
以 .d.ts 爲後綴,例如:runoob.d.ts
聲明文件或模塊的語法格式以下:
declare module Module_Name {
}
TypeScript 引入聲明文件語法格式:
/// <reference path = " runoob.d.ts" />
固然,不少流行的第三方庫的聲明文件不須要咱們定義了,
好比 jQuery 已經有人幫咱們定義好了:
jQuery in DefinitelyTyped。
複製代碼
如下定義一個第三方庫來演示:
CalcThirdPartyJsLib.js 文件代碼:
var Runoob;
(function(Runoob) {
var Calc = (function () {
function Calc() {
}
})
Calc.prototype.doSum = function (limit) {
var sum = 0;
for (var i = 0; i <= limit; i++) {
sum = sum + i;
}
return sum;
}
Runoob.Calc = Calc;
return Calc;
})(Runoob || (Runoob = {}));
var test = new Runoob.Calc();
若是咱們想在 TypeScript 中引用上面的代碼,則須要設置聲明文件 Calc.d.ts,代碼以下:
Calc.d.ts 文件代碼:
declare module Runoob {
export class Calc {
doSum(limit:number) : number;
}
}
聲明文件不包含實現,它只是類型聲明,把聲明文件加入到 TypeScript 中:
CalcTest.ts 文件代碼:
/// <reference path = "Calc.d.ts" />
var obj = new Runoob.Calc();
// obj.doSum("Hello"); // 編譯錯誤
console.log(obj.doSum(10));
下面這行致使編譯錯誤,由於咱們須要傳入數字參數:
obj.doSum("Hello");
複製代碼
TypeScript
,來看下谷歌FLOW
做用: javascript類型檢查
使用步驟
安裝flow, npm init -y -> cnpm i flow-bin -D
package.json中增長執行指令, "flow": "flow"
初始化flow配置文件, npm run flow init
[ignore]: 忽略檢測類型的文件
[include]: 須要檢測類型的文件
在項目中使用以下:
A. 經過註釋(不推薦)
// @flow 註釋以後的內容才能被flow檢測
/*: number */ 在須要檢測的內容這樣註釋, 說明其中類型
// @flow
let a /*: number */ = 3;
a = 'cc'
console.log(a)
B. 直接改寫js結構(須要babel, 相似ts語法了)
安裝bebel, cnpm i babel-cli babel-preset-flow -D
建立.babelrc文件,
{
"presets": [
"flow"
]
}
package.json文件中添加 "build": "babel ./src -d ./dist"
npm run build 經過babel把新增長的: number去除掉, 方便轉碼上線(與下面的指令區分開來)
let a: number = 3;
a = 'abc';
console.log(a);
npm run flow 仍是會檢測數據類型
執行npm run flow, 檢測js內容
複製代碼
number類型:
能夠賦值的類型——數值, NaN, Infinity
let a: number = NaN
string類型
Boolean類型
void類型: 就是js中的undefined
null
Array類型(須要指定array的元素類型) :
let arr: Array<number> = []
any類型
let test: any = 任意數據
複製代碼
// 聲明一個函數類型, 函數參數聲明類型, 返回值也要聲明類型
const sum = (arr: Array<number>): number => {
let result = 0;
arr.forEach(item => {
result += item;
});
return result;
};
// 當聲明一個函數變量時, 說明這個變量是函數,
//參數兩個爲數字, 返回值爲數字
let temp = (a: number, b:number) => number;
// 最多見的ajax, 參數是函數時, 同時箭頭後面表明返回值類型,
// 不寫默認是undefined
const ajax = (callback: (data: Object) => void) {
}
//Maybe類型
// 問號表明能夠是null或者undefined, 函數沒有聲明返回值,
// 即返回值也能夠是undefined
const test = (a: ?number) {
console.log(a)
}
//類型的或操做
// 就是或操做, 二者類型選擇一個
let a = number|string = 10;
a = 'abc'
//對象類型
const ajax = (option: { url:string, type: string,
success:(data: Object) => void }) {
}
ajax()// 報錯, 由於函數參數是對象
複製代碼