Typescript進階之路

宣火魚竹發表於2021-04-17

TypeScript

何為TypeScript

一、程式語言型別

  • 動態型別語言(Dynamically Typed Language)
    • 型別的檢查是在執行時才做
    • 例子---JavaScript、Ruby、Python
  • 靜態型別語言(Statically Typed Language)
    • 型別檢查是在執行前的編譯階段
    • 例子---Java、c、c++

TypeScript提前了型別檢查的時機,它是靜態弱型別語言

二、TypeScript特性

TypeScript(簡稱ts)是一種由微軟開發的自由和開源的程式語言。它是 Javascript 的一個超集,擴充套件了JavaScript的語法. 其本質上是向Javascript語言新增了可選的靜態型別和基於類的物件導向程式設計

  • JavaScript that scales
  • 靜態型別風格的型別系統
  • 從es6到es10以至於exnext的語法支援
  • 相容各種瀏覽器、系統、伺服器的開源語言

三、為什麼使用TypeScript

當使用一個語言庫的時候我們是要有這個需求的時候才用,就像一個元件的狀態管理不復雜你就沒必要用reduxvuex一樣,而TypeScript正是能夠解決我們開發過程中的一些痛點:

  • 程式更容易理解
    • 能夠知道函式或者方法輸入輸出的引數型別,外部條件
    • 不用等執行的時候才能知道資料的型別
    • 更容易理解別人的程式碼不用詢問
  • 效率更高
    • 在不同的程式碼塊和定義中進行跳轉
    • 程式碼自動補全
  • 更少的錯誤
    • 編譯期間能發現大量錯誤
    • 杜絕常見的錯誤(...undefined)
  • 非常好的包容性
    • 完全相容JavaScript
    • 第三方庫可以直接編寫ts檔案

TypeScript的實踐

一、安裝

使用npm管理

npm install -g typescript

安裝完之後可執行tsc <檔名>.ts命令生產.js的檔案,在執行過程中即使因為語法不對導致編譯過程報錯,但還是會生成.js檔案

二、資料型別

Javascript 型別分類:

① 原始資料型別 - primitive values:

  • Boolean
  • Null
  • Undefined
  • Number
  • BigInt
  • String
  • Symbol

② Object

undefinednull==下是相等的,但在全等===條件下是不等的,Null型別,代表“空值”,代表一個空物件指標;Undefined型別,當一個宣告瞭一個變數未初始化時,得到的就是undefined。

其中null表示"沒有物件",即該處不應該有值,典型用法是:

  • 作為函式的引數,表示該函式的引數不是物件
  • 作為物件原型鏈的終點

undefined表示"缺少值",就是此處應該有一個值,但是還沒有定義。典型用法是:
- 變數被宣告瞭,但沒有賦值時,就等於undefined
- 呼叫函式時,應該提供的引數沒有提供,該引數等於undefined
- 物件沒有賦值的屬性,該屬性的值為undefined
- 函式沒有返回值時,預設返回undefined

基於Javascript的資料型別,我們在寫TypeScript的時候就會嚴格按照其型別定義資料,這樣才有便於我們程式碼的維護與規範

1、原始資料型別:

let isType: boolean = true
let count: number = 123
let userName: string = 'chenchenchen'
let u: undefined = undefined
let n: null = null
let notSure: any = 1 //可為任何型別
notSure = "rewq"
notSure = false

2、Object型別:

a、陣列:

let arrOfNumber: number[] = [1,2,3] //數字陣列
arrOfNumber.push(4)

function test() {
	console.log(arguments) //類陣列
	console.log(arguments.length) //長度
	arguments.forEach(item => {}) //報錯
	let arr: any[] = arguments //報錯,不能把類陣列賦值給陣列
}

b、元組:

let user: [string,number] = ["chen",66] //元組
const arr: (number | string)[] = [1,"2",3] //陣列

元組相比於陣列來說是明確的知道有幾個子元素也就是長度固定,而且每個子元素是什麼型別,一般元組的運用場景在匯入csv的資料格式的時候有大用

const memberList: [string,string,number][] = [
	["abb","bcc",12],
	["cvv","asd",24]
]

c、interface介面:

let interface Animal {
	readonly id: number; //只讀不寫,與const類似
	name: string;
	age?: number; //該屬性不是必須
	[propName: string]: any; //還可以有其他的屬性,型別是string,值是任意值
	say(): string; //還可以加方法
} 

let dog: Animal = {
	name: "duoduo",
	age: 6
}

dog.id = 9527 //報錯,只讀不寫

//interface一般可以做到型別別名的作用
interface Point {x: number, y: number} //與型別別名是一樣的效果
type Point {x: number, y: number} //型別別名

function Pythagorean(data: Point) { //型別別名,一眼看出引數的構造
	return Math.sqrt(data.x **2 + data.y **2)
}

Pythagorean({ x : 4, y : 5})

型別別名和介面的區別是有的,介面只能是物件型別,而型別別名還可以是其他型別

d、Function函式

//解構寫法
function add({first , second} : {first : number; second : number}):number {
	return first + second 
}

const add = (x:number,y:number,z?:number):number 
{ //約定輸入輸出都為數字的函式,z為可選引數
	if(typeof(z) == number) {
		return x+y+z
	}else {
		return x+y
	}
}

let add2:string = add //false,函式型別不能賦值給字串型別
let add3:(x:number,y:number,z?:number) => number = add //true,一模一樣的函式型別可以賦值

function operate(): void { //不進行return的函式
	console.log("sadasd")
}

介面型別還可以描述函式型別

interface Itest{
	(x:number,y:number,z?:number): number
} 
let add4:Itest = add //true

e、聯合型別union types

let numberorstring:number | string
numberorstring = "abc"
numberorstring = 123

型別斷言用於處理型別不確定的情況(編譯器無法判斷型別),強行讓編譯器按照你規定的型別處理

function getlength(input:string | number):number {
	const str = input as string
	if(str.length) {
		return str.length
	}else {
		const number = input as number
		return number.toString().length![Alt text](./docker.md)

	}
}

TypeScript也提供了Type Guard這種機制來確認具體型別

f、類Class

類(Class):定義了一切事物的抽象特點,類似於藍圖(比如汽車的一張設計圖)

物件(Object):類的例項(造出來的具體的汽車)

class Car { //定義類
	color: string 
	constructor(color) { //在類例項化的時候才會被執行
		this.color = color
	}
	public start() { //開放的方法
		console.log(`this car is ${this.color}`)
	}
}	

const benz = new Car("black")

class eCar extends Car { //繼承類
	run() {
		console.log(`this running car is ${this.color}`)
	}
}

const tesla = new eCar("white")

class aCar extends Car { //繼承類,重寫方法
	static hight = "100" //靜態屬性
	constructor(color) {
		super(color) //子類的建構函式必須得呼叫父類的建構函式
		console.log(this.color)
	}
	start() {
		console.log(`this aCar is ${this.color}`)
	}
}

const bmw = new aCar("blue")

console.log(benz.start()) //this car is black
console.log(tesla.start()) //this car is white
console.log(tesla.run()) //this running car is white
console.log(bmw.start()) //blue , this aCar is blue
console.loh(aCar.hight) //100

class Person {
	constructor(private _name: string) { //定義了一個私有屬性name

	}
	get name() { //可以讓外部訪問私有屬性
		return this._name + ' 加密'
	}
	set name() { //可以在外部賦值,但一般保護類的私有屬性
		const realName = name.split(' ')[0] // chen
		this._name = realName //私有屬性_name還是"chen"
	}
}

const person = new Person("chen")
console.log(person.name); //chen 加密
person.name = 'chen 加密'
console.log(person.name) //chen 加密

一般我們通過型別註解型別推斷來確認資料的型別,例如

//型別註解
let count: number;
count = 123

//型別推斷
let countInference = 123

一般當ts無法自動分析變數型別的話,我們就需要型別註解來進行標註

相關文章