TypeScript從入門到項目實戰(基礎篇)

前言

你們好,我是八字暱稱,時隔一年多,我終於又發文章啦,什麼?我真懶?個人確很懶😂😂😂前端


那麼,隔了這麼長時間,我又是怎麼想到要發佈一篇文章的呢?java

最近領導讓我統一一哈前端技術棧,首個要統一的就是TypeScript,是的,之後咱們公司前端開發都要用TypeScript,至於TypeScript的好處嘛,你們隨手一百度都能百度到。node

因而乎,我從週二開始,利用空餘時間寫了這篇基礎教程(加班?加班是不可能加班的啦,介輩子都不可能加班的,有沒有加班費,有沒有加班福利,只能早下班才能維持的了生活這樣子😑😑),既然寫了,就要發出來幫(水)助(波)大(經)家(驗)。c++

聲明:✨本系列文章爲基礎教程,不涉及過深的東西,比較適合新手看,若是已經會的同窗,看完這段文字就能夠跑路了😋。程序員

準備工做

前面廢話了一大堆,那麼,該如何上手這樣一門好用又熱門的技術呢如何上手.pnges6

安裝

全局安裝TypeScript:npm install -g typescriptweb

安裝完成以後即在編輯器中編寫代碼(無需額外配置,熱門編輯器對TypeScript支持良好)typescript

開始第一個TypeScript程序——Hello word

在webStrom中新建一個hellowTypeScript.ts文件,輸入:npm

console.log('hellow TypeScript')複製代碼

命令行輸入:tsc hellowTypeScript.ts編程

編譯以後會獲得hellowTypeScript.js文件,使用node運行或者引入頁面仔瀏覽器運行便可

基礎數據類型

布爾類型(boolean)

布爾類型很簡單,只須要在其定義後面添加類型而後賦值便可:

let isClose:boolean=true複製代碼

或者調用Boolean方法:

let isClose:boolean= Boolean(true)複製代碼

其容許值只有兩種:true/false,若是不是這兩種,編譯器就會報錯:

let isClose:boolean=2複製代碼


報錯以下:

Type '2' is not assignable to type 'boolean'.


須要注意的是,使用Boolean構造函數返回的是Boolean對象,因此不能賦值給boolean類型的數據

let isClose:boolean=new Boolean(true)//Type 'Boolean' is not assignable to type 'boolean'.複製代碼


數值類型(number)

數值類型用number來定義:

let num: number = 6
let num2: number = Number(2)//調用number
let num3: number = new Number(2)//調用構造函數,報錯:Type 'Number' is not assignable to type 'number'.
let hexNum: number = 0xf00d//十六進制
let binaryNum: number = 0b1010 //二進制表示法
let octalNum: number = 0o744//八進制表示法
let notANumber: number = NaN
let infinityNumber: number = Infinity複製代碼


字符串類型(string)

使用string定義字符:

let firendNum:number=20
let myName:string='jepson'
let lastName:string=String('smith')
let addres:string=new String('smith')//報錯:Type 'String' is not assignable to type 'string'.
//等價於lastName+myName+' has '+firendNum+' friends'
let message=`${myName}·${lastName} has ${firendNum} friends`複製代碼

null、undefined

在TypeScript中null、undefined是全部類型的子類型,全部其餘類型都可以被賦值爲null和undefined:

let u:undefined=undefined
let n:null=null
let num:number=undefined
let str:string=null複製代碼


你可能會問,爲何在Vue項目中不能這麼用?

由於Vue項目中默認配置了--strictNullChecks標記,這樣也能避免許多錯誤,因此若是想要可以賦值null或者undefined,最好顯式聲明:

let name:string|null|undefined=null複製代碼

symbol(永遠惟一的值)

Symbol是ES6的新原生類型,表示永遠不可變且惟一的值,若是你還不瞭解這個類型,能夠去看阮一峯編寫的《ECMAScript6入門》Symbol篇。在TypeScript中表現爲symbol

let globalKey:symbol=Symbol()
let globalKey2:symbol=Symbol()
console.log(globalKey===globalKey2)//false複製代碼


空值(void)

void表示空值,只能賦值爲null/undefined(全部類型的子類型),若是用於變量中這或許沒什麼用,可是用於函數中表示不返回任何值:

let myFirstName:void=undefined
let myLastName:void=null
function fn1():void {
  return null
}
function fn2():void {
  return undefined
}
function fn3():void {
  console.log('this is fn3')
}複製代碼

any(天使仍是魔鬼?)

any用於不肯定其類型時所指定的類型,表示任何類型,如:第三方庫、後端返回數據不肯定(儘可能要求後端返回的數據肯定)、動態內容等:

let anyValue:any=true
anyValue=20
anyValue='anyValue'
anyValue=Symbol()
anyValue=null
anyValue=undefined
anyValue=new Error('anyvalue')
anyValue=['anyValue']複製代碼


TypeScript中的any類型還曾被一個著名的開發者戲稱道(具體啥名兒,咱也忘了,只記得他說的那句話):

any是TypeScript最大的Bug


注意:指定any類型以後編輯器和編譯器將不會進行檢查,這或許有許多便捷之處,可是從另外一個角度來講,不進行檢查也就表明許多有關的錯誤在編輯器中或者編譯階段不會報錯,因此應儘可能避免在項目中使用any

函數

函數在Javascript中很是重要,由於全部行爲都是經過函數來執行。在《函數式編程指南》一書中指出:

函數是Javascript的一等公民

TypeScript中的函數,須要把輸入和輸出都考慮進去:

//函數聲明式
function add(num1:number,num2:number):number {
  return num1+num2
}

//函數表達式
const reduce=(num1:number,num2:number):number=>num1-num2

console.log(add(1,1))//2
console.log(reduce(1,1))//0
複製代碼


函數中的類型

如上面代碼,函數須要指定輸入和輸出的類型:

  • 少輸入參數、多輸入參數、參數類型不符合都會報錯
  • 若是不指定輸入的類型,默認爲any(不推薦使用any,因此Vue項目中會報錯)
  • 不指定輸出類型則默認爲void,表示無返回結果;若是有返回,TypeScript會根據返回數據自動推斷類型
function runAway() {
  console.log('又是個黑廠,收起行李箱、席子、衣架,提桶跑路')
}複製代碼

上面代碼等價於下面的代碼:

function runAway():void {
  console.log('又是個黑廠,收起行李箱、席子、衣架,提桶跑路')
}複製代碼

下面是個自動推斷類型的例子:

function add(num1:number,num2:number) {
  return num1+num2
}

//自動推斷其類型
const num:number=add(1,2)複製代碼


可選參數與默認參數

可選參數

對於一些參數不是必須的狀況下,可使用可選參數,可選參數使用?:定義,表示這個參數是非必須的:

/**
 * 模擬吃午餐行爲
 * @param mianFood 主食
 * @param mainCourse 主菜
 * @param sideDish 副菜
 * @param soup 湯,這是個非必填參數
 * @param drinks 飲料,這是個非必填參數
 * @param fruits 水果,這是個非必填參數
 */
function haveLunch(mianFood: string, mainCourse: string,sideDish:string,soup?: string, drinks?: string, fruits?: string) {
  const foods = Object.keys(arguments).map((key: string) => arguments[key])
  console.log(`午餐時間到,開始吃午餐,今天的午餐是:${foods.join('、')}`)
}

haveLunch('米飯', '黃豆燉豬蹄', '蠔油生菜')//午餐時間到,開始吃午餐,今天的菜有:米飯、黃豆燉豬蹄、蠔油生菜複製代碼

若是填入可選參數,必須按照順序(假如填入填入飲料,則必須填入湯):

/**
 * 模擬吃午餐行爲
 * @param mianFood 主食
 * @param mainCourse 主菜
 * @param sideDish 副菜
 * @param soup 湯,這是個非必填參數
 * @param drinks 飲料,這是個非必填參數
 * @param fruits 水果,這是個非必填參數
 */
function haveLunch(mainFood: string, mainCourse: string, sideDish: string, soup?: string, drinks?: string, fruits?: string) {
  const foods = [
    `主食:${mainFood ? mainFood : '無'}`,
    `主菜:${mainCourse ? mainCourse : '無'}`,
    `副菜:${sideDish ? sideDish : '無'}`,
    `湯:${soup ? soup : '無'}`,
    `飲料:${drinks ? drinks : '無'}`,
    `水果:${fruits ? fruits : '無'}`,
  ]
  console.log(`午餐時間到,開始吃午餐,今天的午餐有:\n${foods.join('\n')}`)
}

//   午餐時間到,開始吃午餐,今天的午餐有:
//   主食:米飯
//   主菜:黃豆燉豬蹄
//   副菜:蠔油生菜
//   湯:可樂(可樂原本是飲料的)
//   飲料:無
//   水果:無
haveLunch('米飯', '黃豆燉豬蹄', '蠔油生菜', '可樂')

//   午餐時間到,開始吃午餐,今天的午餐有:
//   主食:米飯
//   主菜:黃豆燉豬蹄
//   副菜:蠔油生菜
//   湯:西紅柿蛋湯
//   飲料:可樂
//   水果:無
haveLunch('米飯', '黃豆燉豬蹄', '蠔油生菜', '西紅柿蛋湯','可樂')複製代碼

須要注意的是:可選參數後面不能帶必選參數,必選參數前面只能是0或1個必選參數

/**
 * 模擬吃午餐行爲
 * @param mianFood 主食
 * @param mainCourse 主菜
 * @param sideDish 副菜
 * @param soup 湯,這是個非必填參數
 * @param drinks 飲料,這是個非必填參數
 * @param fruits 水果,這是個非必填參數
 */
//報錯:A required parameter cannot follow an optional parameter.
function haveLunch(mainFood: string, mainCourse: string, sideDish: string, soup?: string, drinks: string, fruits?: string) {
  const foods = [
    `主食:${mainFood ? mainFood : '無'}`,
    `主菜:${mainCourse ? mainCourse : '無'}`,
    `副菜:${sideDish ? sideDish : '無'}`,
    `湯:${soup ? soup : '無'}`,
    `飲料:${drinks ? drinks : '無'}`,
    `水果:${fruits ? fruits : '無'}`,
  ]
  console.log(`午餐時間到,開始吃午餐,今天的午餐有:\n${foods.join('\n')}`)
}複製代碼

默認參數

默認參數是ES6的一個新特性,若是還不太瞭解這個特性的同窗,能夠參考阮一峯寫的《ECMAScript入門教程》函數篇

用於爲那些非必填項設置默認值:

/**
 * 模擬吃午餐行爲
 * @param mianFood 主食
 * @param mainCourse 主菜
 * @param sideDish 副菜
 * @param soup 湯,默認爲無,非必填參數
 * @param drinks 飲料,默認爲白開水(沒有飲料就喝喝白開水吧),非必填參數
 * @param fruits 水果,默認爲無,非必填參數
 */
function haveLunch(mainFood: string, mainCourse: string, sideDish: string, soup: string='無', drinks: string='白開水', fruits: string='無') {
  const foods = [
    `主食:${mainFood ? mainFood : '無'}`,
    `主菜:${mainCourse ? mainCourse : '無'}`,
    `副菜:${sideDish ? sideDish : '無'}`,
    `湯:${soup ? soup : '無'}`,
    `飲料:${drinks ? drinks : '無'}`,
    `水果:${fruits ? fruits : '無'}`,
  ]
  console.log(`午餐時間到,開始吃午餐,今天的午餐有:\n${foods.join('\n')}`)
}

// 午餐時間到,開始吃午餐,今天的午餐有:
// 主食:米飯
// 主菜:黃豆燉豬蹄
// 副菜:蠔油生菜
// 湯:無
// 飲料:白開水
// 水果:無
haveLunch('米飯', '黃豆燉豬蹄', '蠔油生菜')複製代碼

默認參數與可選參數不一樣:

  1. 默認參數沒有位置限制,第一個參數也能設置默認參數,後面能夠帶必選參數
  2. 默認參數若是傳入undefinednull不會取代默認值,而可選參數會直接複製;利用這一特性能夠爲每一個參數設置默認值,若是是默認值能夠傳入undefinednull
// 午餐時間到,開始吃午餐,今天的午餐有:
// 主食:米飯
// 主菜:黃豆燉豬蹄
// 副菜:蠔油生菜
// 湯:無(傳入的是undefined)
// 飲料:白開水(傳入的是null)
// 水果:西瓜
haveLunch('米飯', '黃豆燉豬蹄', '蠔油生菜',undefined,null,'西瓜')複製代碼


=>與箭頭函數

你必定好奇,=>不是ES6箭頭函數嗎,這還有什麼可講的?


下載 (1).jpg

在TypeScript類型定義中=>用於表示函數,左邊是輸入類型,右邊是輸出類型;

而在ES6中,=>表明的是一個箭頭函數,左邊參數,右邊代碼塊


下面例子中展現了TypeScript類型定義中的和ES6的=>之間的區別

let add: (num1: number, num2: number) => number
add = (num1, num2) => num1 + num2複製代碼

rest參數(剩餘參數)

rest參數是ES6的新特性,還不瞭解的同窗請看傳送門:《ECMAScript入門教程》函數篇

在TypeScript中咱們能夠爲rest參數設定類型:

function add(num1:number,num2:number,...numArr:number[]):number {
  let num=num1+num2
  numArr.forEach((n:number)=>{
    num+=n
  })
  return num
}

console.log(add(1,1,1,1,1,1))//6複製代碼

interface(接口)

在面嚮對象語言中,接口(Interfaces)是一個很重要的概念,它是對行爲的抽象,而具體如何行動須要由類(classes)去實現(implement)。


TypeScript中的interface(接口)很是靈活,經常使用與對類的部分行爲抽象、規定對象的形狀(哪些屬性/方法)

interface User {
  username:string;
  password:string;
}

//下面這個寫法會報錯
const u:User={
  username: 'admin',
  password: 12345678,//報錯:Type 'number' is not assignable to type 'string'.
  level:1//報錯:Type '{ username: string; password: string; level: number; }' is not assignable to type 'User'.
}

//這個寫法不會報錯
const u2:User={
  username: 'admin',
  password: '12345678'
}
複製代碼

可選屬性

interface規定了對象應該有那些屬性,而有時候對象的某些屬性並非固定有的,這時候咱們能夠定義一個可選屬性,即便缺乏可選屬性,仍然不會報錯:

interface User {
  username:string;
  password:string;
  level?:number
}

const u:User={
  username: 'admin',
  password: '12345678'
}複製代碼

只讀屬性

有這樣一種應用場景:但願對象在建立的時候初始化值,而一旦初始化以後便不能改變其值。這時候只讀屬性就派上用場了:

interface User {
  readonly username:string;
  password:string;
  level?:number
}

const u:User={
  username: 'admin',
  password: '12345678',
  level:1
}

u.username='Admin'//報錯:Cannot assign to 'username' because it is a read-only property.複製代碼

函數屬性

那麼,如何指定對象中的函數呢?

採用functionName(...args:dataType):returnType的形式指定:

interface User {
  readonly username:string;
  password:string;
  level?:number;
  upgrade(level:number):number
}

const u:User={
  username: 'admin',
  password: '12345678',
  level:1,
  upgrade(level:number): number {
    this.level+=level
    return this.level
  }
}
console.log(u.upgrade(2))//3複製代碼


動態可索引屬性實現僞數組

前面說過,TypeScript的interface很是靈活,能夠用動態可索引屬性,因此咱們能夠利用這點實現僞數組類型:

interface PseudoArray{
  [index:number]:number
}

const pseudoArray={
  0:20,
  1:11,
  2:33
}複製代碼

或者動態對象:

const pseudoArray = {
  0: 20,
  1: 11,
  2: 33
}

interface DynamicObject {
  [key: string]: any
}

const dynamicObject = {
  name: 'jepson',
  address: 'anywhere'
}複製代碼

接口定義函數類型

可使用接口爲函數定義類型:

interface Add {
  (num1: number, num2: number): number
}

let add: Add = (num1, num2) => num1 + num2
複製代碼

接口間的繼承

什麼是繼承?如下原話摘自維基百科:

繼承(英語:inheritance)是面向對象軟件技術當中的一個概念。若是一個類別B「繼承自」另外一個類別A,就把這個B稱爲「A的子類」,而把A稱爲「B的父類別」也能夠稱「A是B的超類」。繼承可使得子類具備父類別的各類屬性和方法,而不須要再次編寫相同的代碼。在令子類別繼承父類別的同時,能夠從新定義某些屬性,並重寫某些方法,即覆蓋父類別的原有屬性和方法,使其得到與父類別不一樣的功能。另外,爲子類追加新的屬性和方法也是常見的作法。 通常靜態的面向對象編程語言,繼承屬於靜態的,意即在子類的行爲在編譯期就已經決定,沒法在運行期擴展。

有些編程語言支持多重繼承,即一個子類能夠同時有多個父類,好比C++編程語言;而在有些編程語言中,一個子類只能繼承自一個父類,好比Java編程語言,這時能夠透過實現接口來實現與多重繼承類似的效果。

現今面向對象程序設計技巧中,繼承並不是以繼承類別的「行爲」爲主,而是繼承類別的「類型」,使得組件的類型一致。另外在設計模式中提到一個守則,「多用合成,少用繼承」,此守則也是用來處理繼承沒法在運行期動態擴展行爲的遺憾。

TypeScript中的繼承比較靈活,可以多重繼承,用extends實現:

/**
 * 抽象出動物的一些基本活動
 */
interface Animal {
  eat(food: string): void;

  run(): void;

  sleep(): void;
}

/**
 * 人類的本質也是動物,因此應該從動物繼承這些基本屬性
 */
interface Human extends Animal {
  name: string;
  hair: string;
  readonly birthday: Date;
  sex: 'MAN' | 'WOMAN';//此處的聯合類型將會在下一篇中講到講到
  interest: string;
  age: number;
}

/**
 * 男性本質上是人類,因此應該繼承人類的一些特性
 */
interface Man extends Human {
  age: number;//男生們對本身的年齡看的很淡
}

/**
 * 女性本質上是人類,因此應該繼承人類的一些特性
 */
interface Woman extends Human {
  age: 18;//女生們都但願本身永遠18歲,因此Woman能夠有本身的年齡,而不是從Human裏面繼承,這個叫作
}

const epson: Man = {
  age: 28,
  birthday: new Date(1992,1,1),
  hair: '短髮',
  interest: '打籃球 打遊戲 釣魚',
  name: 'epson',
  sex: 'MAN',
  eat(food: string): void {
    console.log(`${this.name}${food}`)
  },
  run(): void {
    console.log(`${this.name}開始跑步`)
  },
  sleep(): void {
    console.log(`${this.name}躺下來休息`)
  }
}

const marry: Woman = {
  age: 19,//Type '19' is not assignable to type '18'.
  birthday: new Date(1992,1,1),
  hair: '長髮',
  interest: '逛街 吃美食 八卦',
  name: 'marry',
  sex: 'MAN',
  eat(food: string): void {
    console.log(`${this.name}${food}`)
  },
  run(): void {
    console.log(`${this.name}開始跑步`)
  },
  sleep(): void {
    console.log(`${this.name}躺下來休息`)
  }
}複製代碼


數組

TypeScript定義數組類型,使得數組中不可以有除了指定類型以外的其餘類型,在編輯器和編譯階段會報錯(可是不影響編譯)。

接下來咱們看看怎麼定義數組

類型+數組字面量定義

let numArr:number[]
numArr=[1,2,3]
numArr=[1,2,3,'4']//報錯:Type 'string' is not assignable to type 'number'.
numArr=[1,2,3,false]//報錯:Type 'false' is not assignable to type 'number'.複製代碼

數組泛型定義數組

數組泛型支持定義多種類型

let numArr:Array<string|number>
numArr=[1,2,3]
numArr=[1,2,3,'4']
numArr=[1,2,3,false]//報錯:Type 'false' is not assignable to type 'number'.複製代碼

在實際開發中,更推薦這種方式定義數組,由於看上去更加明瞭、靈活,更像是一個類型

接口定義數組

前面說過,interface是個很重要的概念,它很靈活、可以應用於多種場景,除了能夠用來定義僞數組,也能夠用來定義真數組,其類型定義和數組泛型同樣靈活:

interface NumberArray{
  [index:number]:number|string
}
let numArr:NumberArray
numArr=[1,2,3]
numArr=[1,2,3,'4']//報錯:Type 'string' is not assignable to type 'number'.
numArr=[1,2,3,false]//報錯:Type 'false' is not assignable to type 'number'.複製代碼

元組

對於指定元素數量和類型的數組,推薦使用元組定義:

const position: [number, number] = [114.118702, 22.647837]//定義一個經緯度位置信息
let roleArr: [string, string, string]
roleArr= ['superAdmin', 'admin', 'user']//定義一個角色數組,只有超級管理員、普通管理員、用戶三種角色
roleArr= ['superAdmin', 'admin', 'user','tourist']//報錯:Type '[string, string, string, string]' is not assignable to type '[string, string, string]'.、

let data: [string,number,boolean]
data= ['superAdmin',0,false]//定義一個角色數組,只有超級管理員、普通管理員、用戶三種角色
console.log(data[0].toString())
console.log(data[1].subString(0,1))//訪問元素將會自動得到其類型,因此這裏將會報錯:Property 'subString' does not exist on type 'number'.
console.log(data[2])
console.log(data[4].toString())//訪問越界元素將會報錯: Object is possibly 'undefined'.複製代碼


枚舉

如下摘自維基百科:

數學計算機科學理論中,一個集的枚舉是列出某些有窮序列集的全部成員的程序,或者是一種特定類型對象的計數。這兩種類型常常(但不老是)重疊。

枚舉是一個被命名的整型常數的集合,枚舉在平常生活中很常見,例如表示星期的SUNDAY、MONDAY、TUESDAY、WEDNESDAY、THURSDAY、FRIDAY、SATURDAY就是一個枚舉。

枚舉項有兩種類型:常數項(constant member)和計算所得項(computed member)。


當知足如下條件時,枚舉成員被看成是常數:

  • 不具備初始化函數而且以前的枚舉成員是常數。在這種狀況下,當前枚舉成員的值爲上一個枚舉成員的值加 1。但第一個枚舉元素是個例外。若是它沒有初始化方法,那麼它的初始值爲 0。
  • 枚舉成員使用常數枚舉表達式初始化。常數枚舉表達式是 TypeScript 表達式的子集,它能夠在編譯階段求值。當一個表達式知足下面條件之一時,它就是一個常數枚舉表達式:
  • 數字字面量
  • 引用以前定義的常數枚舉成員(能夠是在不一樣的枚舉類型中定義的)若是這個成員是在同一個枚舉類型中定義的,可使用非限定名來引用
  • 帶括號的常數枚舉表達式
  • +, -, ~ 一元運算符應用於常數枚舉表達式
  • +, -, *, /, %, <<, >>, >>>, &, |, ^ 二元運算符,常數枚舉表達式作爲其一個操做對象。若常數枚舉表達式求值後爲 NaN 或 Infinity,則會在編譯階段報錯


TypeScript的枚舉(enum)很是靈活,默認自動賦值,好比定義一週的天數:

enum Week {
  Monday,
  Tuesday,
  Wednesday,
  Thursday,
  Friday,
  Saturday,
  Sunday
}複製代碼

其編譯以後的結果:

var Week;
(function (Week) {
    Week[Week["Monday"] = 0] = "Monday";
    Week[Week["Tuesday"] = 1] = "Tuesday";
    Week[Week["Wednesday"] = 2] = "Wednesday";
    Week[Week["Thursday"] = 3] = "Thursday";
    Week[Week["Friday"] = 4] = "Friday";
    Week[Week["Saturday"] = 5] = "Saturday";
    Week[Week["Sunday"] = 6] = "Sunday";
})(Week || (Week = {}));
//# sourceMappingURL=doc1.js.map複製代碼

手動賦值

值爲數字

當值爲數字時,會根據手動賦值逐個遞增:

enum Week {
  Monday=1,
  Tuesday,
  Wednesday,
  Thursday,
  Friday,
  Saturday,
  Sunday
}複製代碼

編譯結果爲:

var Week;
(function (Week) {
    Week[Week["Monday"] = 1] = "Monday";
    Week[Week["Tuesday"] = 2] = "Tuesday";
    Week[Week["Wednesday"] = 3] = "Wednesday";
    Week[Week["Thursday"] = 4] = "Thursday";
    Week[Week["Friday"] = 5] = "Friday";
    Week[Week["Saturday"] = 6] = "Saturday";
    Week[Week["Sunday"] = 7] = "Sunday";
})(Week || (Week = {}));
//# sourceMappingURL=doc1.js.map複製代碼

須要注意的是:若是值有重複項,TypeScript是不會發覺的,因此應該避免此類型狀況:

//TypeScript
enum Week {
  Monday=1,
  Tuesday,
  Wednesday=1,
  Thursday,
  Friday,
  Saturday,
  Sunday
}
//編譯後
var Week;
(function (Week) {
    Week[Week["Monday"] = 1] = "Monday";
    Week[Week["Tuesday"] = 2] = "Tuesday";
    Week[Week["Wednesday"] = 1] = "Wednesday";
    Week[Week["Thursday"] = 2] = "Thursday";
    Week[Week["Friday"] = 3] = "Friday";
    Week[Week["Saturday"] = 4] = "Saturday";
    Week[Week["Sunday"] = 5] = "Sunday";
})(Week || (Week = {}));
//# sourceMappingURL=doc1.js.map複製代碼

值爲字符串

賦值爲字符串以後,後面的都須要手動賦值(不像數字那樣會自動遞增),當某個值再次賦值爲數字纔會自動遞增:

//TypeScript
enum Week {
  Monday=1,
  Tuesday='2',
  Wednesday=3,
  Thursday,
  Friday,
  Saturday,
  Sunday
}
//編輯結果
var Week;
(function (Week) {
    Week[Week["Monday"] = 1] = "Monday";
    Week["Tuesday"] = "2";
    Week[Week["Wednesday"] = 3] = "Wednesday";
    Week[Week["Thursday"] = 4] = "Thursday";
    Week[Week["Friday"] = 5] = "Friday";
    Week[Week["Saturday"] = 6] = "Saturday";
    Week[Week["Sunday"] = 7] = "Sunday";
})(Week || (Week = {}));
//# sourceMappingURL=doc1.js.map複製代碼

計算所得項

枚舉項中的計算所得項:


enum Color {
  Red,
  Green,
  Blue = 'blue'.length
}複製代碼

上面示例不會報錯,可是若是計算所得項後面還有未手動賦值項,則會由於沒法獲取初始值而報錯:

enum Color {
  Red,
  Green,
  Blue = 'blue'.length,
  Yellow//Enum member must have initializer.
}複製代碼

因此,計算所得項後面必須手動賦值或者放在枚舉最後:

enum Color {
  Red,
  Green,
  Blue = 'blue'.length,
  Yellow=3
}複製代碼

須要注意的是,在有字符串常量的枚舉中,不容許有計算所得項:

enum Color {
  Red,
  Green,
  Blue = 'blue'.length,//Computed values are not permitted in an enum with string valued members.
  Yellow='3'
}複製代碼

常數枚舉

常數枚舉與普通枚舉只相差一個const,其區別是:在編譯階段會被刪除,且不能包含計算所得項:

//TypeScript
//定義一個五行枚舉
const enum FiveElements {
  metal = '金',
  wood = '木',
  water = '水',
  fire = '火',
  earth = '土'
}
console.log(`五行相生:
${FiveElements.wood}${FiveElements.fire}
${FiveElements.fire}${FiveElements.earth}
${FiveElements.earth}${FiveElements.metal}
${FiveElements.metal}${FiveElements.water}
${FiveElements.water}${FiveElements.wood}`)

console.log(`五行相剋:
${FiveElements.wood}${FiveElements.earth}
${FiveElements.earth}${FiveElements.water}
${FiveElements.water}${FiveElements.fire}
${FiveElements.fire}${FiveElements.metal}
${FiveElements.metal}${FiveElements.wood}`)

//編譯結果
console.log(`五行相生:
${"\u6728" /* wood */}${"\u706B" /* fire */}
${"\u706B" /* fire */}${"\u571F" /* earth */}
${"\u571F" /* earth */}${"\u91D1" /* metal */}
${"\u91D1" /* metal */}${"\u6C34" /* water */}
${"\u6C34" /* water */}${"\u6728" /* wood */}`);
console.log(`五行相剋:
${"\u6728" /* wood */}${"\u571F" /* earth */}
${"\u571F" /* earth */}${"\u6C34" /* water */}
${"\u6C34" /* water */}${"\u706B" /* fire */}
${"\u706B" /* fire */}${"\u91D1" /* metal */}
${"\u91D1" /* metal */}${"\u6728" /* wood */}`);
//# sourceMappingURL=doc1.js.map複製代碼

外部枚舉

外部枚舉指的是使用declare定義的枚舉,他可以在外部被引用:

//enum.ts
declare enum FiveElements {
  metal = '金',
  wood = '木',
  water = '水',
  fire = '火',
  earth = '土'
}
//main.ts
console.log(`五行相生:
${FiveElements.wood}${FiveElements.fire}
${FiveElements.fire}${FiveElements.earth}
${FiveElements.earth}${FiveElements.metal}
${FiveElements.metal}${FiveElements.water}
${FiveElements.water}${FiveElements.wood}`)

console.log(`五行相剋:
${FiveElements.wood}${FiveElements.earth}
${FiveElements.earth}${FiveElements.water}
${FiveElements.water}${FiveElements.fire}
${FiveElements.fire}${FiveElements.metal}
${FiveElements.metal}${FiveElements.wood}`)複製代碼

其編譯結果爲:

//main.js
console.log(`五行相生:
${FiveElements.wood}${FiveElements.fire}
${FiveElements.fire}${FiveElements.earth}
${FiveElements.earth}${FiveElements.metal}
${FiveElements.metal}${FiveElements.water}
${FiveElements.water}${FiveElements.wood}`);
console.log(`五行相剋:
${FiveElements.wood}${FiveElements.earth}
${FiveElements.earth}${FiveElements.water}
${FiveElements.water}${FiveElements.fire}
${FiveElements.fire}${FiveElements.metal}
${FiveElements.metal}${FiveElements.wood}`);
//# sourceMappingURL=doc1.js.map
//enum.js
//# sourceMappingURL=doc2.js.map複製代碼

外部枚舉在編譯階段會被刪除,常出如今聲明文件中,能夠結合常數枚舉使用:

declare const enum FiveElements {
  metal = '金',
  wood = '木',
  water = '水',
  fire = '火',
  earth = '土'
}複製代碼

結語

TypeScript基礎篇到這裏就結束了。對於學過強類型的語言(java、c、c++等)的同窗來講TypeScript仍是很簡單好用的,不少概念都是從強類型語言中學習(是的,學習,程序員的事,怎麼能叫抄呢😎😎)過來的;對於從一開始就學習前端的同窗而言,一開始老是有點痛的,習慣了就好😋😋。


建議:本身寫寫簡單地程序練練手,多熟悉熟悉。


另外,文章寫得可能不全面、不對或者有難理解的地方,歡迎在評論區踊躍發言哦😊😊

同時,各位大佬噴的輕一點,畢竟:


我是八字暱稱,咱們下篇見

                                                    

相關文章
相關標籤/搜索