TypeScript入門教程

TypeScript是什麼

  • TypeScript是JavaScript的一個超集
  • TypeScript須要編譯爲JavaScript才能運行(語法糖)
  • TypeScript提供了類型系統,規範相似Java
  • TypeScript提供了ES6的支持,也能夠支持部分ES7草案的特性,不用擔憂TypeScript沒法兼容目前主流的JavaScript解釋器

環境安裝

  1. 安裝node.js
    https://nodejs.org/en/download/
  2. 安裝TypeScript包,這就是TS的編譯器
    npm install -g typescript
  3. 檢查TypeScript是否安裝成功
    tsc -v

TypeScript開發工具

TypeScript是開源的項目,由微軟開發和維護,所以最初只有微軟的 Visual Studio 支持。如今,出現了更多自己支持或者經過插件支持 TypeScript 語法、智能提示、糾錯、甚至是內置編譯器的文本編輯器和IDE。html

  • Visual Studio Code,微軟出品,內置支持TypeScript特性
  • Sublime Text的官方插件
  • WebStorm的最新版本內置支持

類型系統

原始數據類型

主類型:node

string、number、boolean

特殊類型:typescript

null、undefined、symbol(ES6)

基礎類型聲明與使用:npm

string:
    let name: string = ‘Alice’;
    let desc: string = `my name is ${name}`;
number:
    let norm: number = 666;
    let binaryNum: number = 0b111;
    let hexNum: number = 0xfff;
    let octalNum: number = 0o17;
    let nan: number = NaN;
    let infinity: number = Infinity;
boolean:
    let yet: boolean = true;
    let flag: boolean = Boolean(0);
null:
    let n: null = null;
undefined:
    let u: undefined = undefined;
symbol:
    let s: Symbol = Symbol(2);
void:
    let v2: void = null;
    let v5: void = undefined;

任意值類型

let name: string = ‘Tom’;
    name = 666;

    demo.ts(2,1): error TS2322: Type '666' is not assignable to type 'string'.
使用any類型:
```
    let name: any = ‘Tom’;
    name = 666;
```
隱式任意值類型:
    let name;
    name = ‘Tom’;
    name = 666;

等價於:

    let name : any;    
    name = ‘Tom’;
    name = 666;

類型推論

TS會在沒有明確指定類型的時候推測出一個類型,這就是類型推論編輯器

let user = ‘Tom’;
user = 666;

demo.ts(2,1): error TS2322: Type '666' is not assignable to type 'string'.

聯合類型

TS中的聯合類型表示取值可爲多種類型中的一種:函數

let user: string | number;
user = 666;
user = ‘Tom’;

訪問聯合類型的屬性或方法時,只能訪問全部類型的共有方法:工具

function test(param: string|number){
return param.length;
}

demo.ts(2,18): error TS2339: Property 'length' does not exist on type 'string | number’.

類型斷言

類型斷言能夠手動指定一個值的類型,可是類型斷言不是強制類型轉換,TypeScript編譯器不支持強制類型轉換。開發工具

function test(param: number|string){
    if((<string>param).length)
        return (<string>param).length;
    else    
        return param.toString().length    
}

對象的類型—接口

interface Sport {
    name: string,
    teamwork: boolean
}

let football: Sport = {
    name: 'soccer',
    teamwork: true
}

可選屬性:this

interface Sport {
    name: string,
    teamwork: boolean,
    needPg?: boolean
}

let football: Sport = {
    name: 'soccer',
    teamwork: true
}

任意屬性:.net

interface Sport {
    name: string,
    teamwork: boolean,             
    needPg?: boolean,
    [other: string]: any
}

let football: Sport = {
    name: 'soccer',
    teamwork: true,
    needPg: true,
    count: 22
}

一旦定義任意屬性,那麼肯定屬性和可選屬性的類型必須是它的子屬性

只讀屬性:

interface Sport {
    readonly name: string,
    teamwork: boolean
 }

let football: Sport = {
    name: 'soccer',
    teamwork: true
}

函數的類型

函數聲明

function avg(x: number,y:number):number{
return (x+y)/2;
}

函數表達式

let avg = function(x:number,y:number):number{
return (x+y)/2;
}

or

let avg: (x:number,y:number) => number = function(x:number,y:number):number{
return (x+y)/2;
}

函數可選參數:

function avg(x: number,y?:number):number{
if(y){
 return (x+y)/2;
}else{
return x;
}
}

可選參數必須在必選參數的後面

函數的可選參數與默認值:

function avg(y:number = 10,x: number):number{
if(y){
 return (x+y)/2;
}else{
return x;
}
}

TypeScript會將添加默認值的參數識別爲可選參數,此時不受「可選參數必須在必選參數的後面」的限制

函數重載:

TypeScript中經過爲一個函數進行屢次函數定義,並實現函數完成重載

function reverse(x: number): number;
function reverse(x: string): string;
function reverse(x: any):any{
if(typeof x == ‘number’){
 return Number(x.toString().split(‘’).reverse().join(‘’));
}else{
return x.split(‘’).reverse().join(‘’);
}
}

面向對象的函數重載:

interface A{
    say(x:number);
    say(x:string);
}

class AA implements A{
    say (x:any){
   if(typeof x == ‘string’)
             console.log(‘string’,x);
        else
console.log(‘number’,x);
    }
}
console.log((new AA()).say(1));
console.log((new AA()).say('123'));

字符串字面量類型

該類型約束值只能是某幾個字符串的一個,這是在編譯器層面作的約束,並不會改變生成的js代碼

type Name = 'abc' | 'def' | 'mn';
function demo(e: Name): void{
    console.log(e);
}
demo(‘abc');

TypeScript與面向對象

class Block {
    private hash: string;
    private prevHash: string;
    private nonce: number;
    constructor (hash: string, prevHash: string, nonce = 0){
        this.hash = hash;
        this.prevHash = prevHash;
        this.nonce = nonce;
    }
    public get $hash(): string {
        return this.hash;
    }
    public set $hash(value: string) {
        this.hash = value;
    }
    public get $prevHash(): string {
        return this.prevHash;
    }
    public set $prevHash(value: string) {
        this.prevHash = value;
    }
    public get $nonce(): number {
        return this.nonce;
    }
    public set $nonce(value: number) {
        this.nonce = value;
    }
    public computeHash(){
        let sha256 = crypto.createHash('sha256');
        sha256.update(`${this.prevHash}${this.nonce.toString(16)}`,'utf8');
        let hash = sha256.digest('hex');
        return hash;
    }
}

抽象類

TypeScript中抽象類不容許被實例化

abstract class BtcBlock {
    public abstract computeHash(x:string):string;
}
class Block extends BtcBlock {
    public computeHash(x:string):string{
        return `btc${x}`;
    };
}

接口

上節已提到,TS中的接口就是抽象多個類的共有屬性與方法,做爲對象的類型而存在

interface Alarm {
    alert(): void;
}
interface Light {
    lightOn(): void;
    lightOff(): void;
}
class Auto implements Alarm, Light {
    alert(){
        console.log('car alart');
    }
    lightOn(){
        console.log('car light on');
    }
    lightOff(){
        console.log('car light off');
    }
}

泛型

即在定義類、函數或接口時不指定具體類型,而在使用時指定類型的特性。

function useGeneric<T>(length: number,value: T):Array<T>{
    let array: Array<T> = [];
    for(let i=0;i<length;i++){
        array.push(value);
    }
    return array;
}
useGeneric<string>(2,'hello world');
useGeneric<number>(100,1);

裝飾器(註解)

裝飾器是特殊類型的聲明,能夠被附加到類聲明、方法、訪問符、屬性或參數上,具體文檔:
https://www.tslang.cn/docs/ha...

裝飾器並未成爲ES7的規範,所以將來可能會發生改變,並不推薦你們在線上項目中使用

裝飾器之方法裝飾器

function enumerable(value: boolean) {
    return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
        descriptor.enumerable = value;
    };
}

class Greeter {
    greeting: string;
    constructor(message: string) {
        this.greeting = message;
    }

    @enumerable(false)
    greet() {
        return "Hello, " + this.greeting;
    }
}

TypeScript與JavaScript生態

描述非TypeScript編寫的類庫的類型,須要聲明類庫所暴露出的API,相似於C的頭文件,在TypeScript中文件類型則爲 .d.ts

  • 使用TypeScript生態提供的聲明文件
    npm install @types/node
    聲明文件列表:
    http://npm.vdian.net/browse/k...
  • 本身編寫聲明文件declare module 「name」;
相關文章
相關標籤/搜索