TypeScript保姆級基礎(chǔ)教程
什么是 TypeScript?
TypeScript,簡稱 ts,是微軟開發(fā)的一種靜態(tài)的編程語言,它是 JavaScript 的超集。 那么它有什么特別之處呢?
- 簡單來說,js 有的 ts 都有,所有js 代碼都可以在 ts 里面運(yùn)行。
- ts 支持類型支持,ts = type +JavaScript。
那么 ts 和 js 有什么區(qū)別呢?
JavaScript 屬于動(dòng)態(tài)編程語言,而ts 屬于靜態(tài)編程語言。
js:邊解釋邊執(zhí)行,錯(cuò)誤只有在運(yùn)行的時(shí)候才能發(fā)現(xiàn)
ts:先編譯再執(zhí)行,在寫的時(shí)候就會(huì)發(fā)現(xiàn)錯(cuò)誤了(ts不能直接執(zhí)行,需要先編譯成 js )
ts 完全支持 js ,可以直接轉(zhuǎn)換
ts 有類型支持,有強(qiáng)大的代碼類型提示
相信大家現(xiàn)在對 ts 有一個(gè)基本的了解了,那么它應(yīng)該怎么使用呢? 首先先做一些簡單的準(zhǔn)備工作:
- 下載一個(gè)全局的包
npm i -g typescript #或者 yarn global add typescript
- 打開cmd 輸入命令 tsc -v 查看包是否下載成功
當(dāng) cmd 輸入指令出現(xiàn)版本號(hào),就說明下載成功啦
首先打開 vscode, 新建一個(gè) .ts文件。
如 hello.ts
接下來就可以書寫 ts 的代碼啦!
- 新建文件,如 hello.ts。(ts文件的后綴名都是 .ts哦)
- 書寫代碼
編譯代碼:在終端輸入 tsc ./hello.ts, 會(huì)自動(dòng)生成一個(gè)js 文件,接下來就可以用 node 命名來運(yùn)行js 的文件,在瀏覽器打開看效果啦
如果不想下載包的話,也可以在線運(yùn)行,鏈接如下: 在線運(yùn)行 接下來了解一下 ts 的類型注解
什么是類型注解?
就是給變量添加類型約束,可以顯示標(biāo)記出代碼中的意外行為,從而降低了發(fā)生錯(cuò)誤的可能性 語法:
let 變量名: 類型 = 初始值
let age: number = 18
這樣寫有啥好處捏?更好的規(guī)定了數(shù)據(jù)的類型,避免了不必要的錯(cuò)誤。 如果你不小心寫錯(cuò)了,他會(huì)直接提示你類型錯(cuò)誤哦。是不是很貼心呢?
代碼中的 : number
就是類型注解。
注:這里的代碼錯(cuò)誤提示,我是下載了一個(gè)插件才有的。如果大家也想有提示的話,可以在 vscode 里面下載。我把插件的截圖貼在下面。
ts 的類型
ts 的常用基礎(chǔ)類型分為兩種: js 已有類型
原始類型:number/string/boolean/null/undefined/symbol
對象類型:object
(包括,數(shù)組、對象、函數(shù)等對象)
ts 新增類型
- 聯(lián)合類型
- 自定義類型(類型別名)
- 接口
- 元組
- 字面量類型
- 枚舉
- void
- any
- 等等
原始類型: number/string/boolean/null/undefined/symbol 語法比較簡單
基本和 js 差別不大
// 數(shù)值類型 let age: number = 18 // 字符串類型 let myName: string = '小花' // 布爾類型 let isLoading: boolean = false // undefined let un: undefined = undefined // null let timer:null = null // symbol let uniKey:symbol = Symbol()
類型推論 在 TS 中,某些沒有明確指定類型的情況下,TS 的類型推論機(jī)制會(huì)自動(dòng)提供類型。好處:由于類型推論的存在,有些情況下的類型注解可以省略不寫 有如下兩種場景:
- 聲明變量并初始化時(shí)
- 決定函數(shù)返回值時(shí)
已知函數(shù)的兩個(gè)參數(shù)都是number
類型,那么該函數(shù)的返回值也是 number
類型。
聯(lián)合類型
需求:如何定義一個(gè)變量可以是null也可以是 number 類型? 這個(gè)時(shí)候,前面所學(xué)的已經(jīng)不能滿足我們的需求了,就需要用到一個(gè)新的類型 - 組合類型。 語法:
let 變量: 類型1 | 類型2 | 類型3 .... = 初始值 let arr1 :number | string = 1 // 可以寫兩個(gè)類型
注意: 這里的 |
豎線,在 TS 中叫做聯(lián)合類型,即:由兩個(gè)或多個(gè)其他類型組成的類型,表示可以是這些類型中的任意一種。不要和 js 中的 ||
搞混哦。 應(yīng)用場景: 定時(shí)器id
// | 聯(lián)合類型 變量可以是兩種類型之一 let timer:number|null = null timer = setTimeout()
類型別名
在我們定義類型的時(shí)候,有時(shí)候自己定義的類型名往往很長,這個(gè)時(shí)候就需要在定義個(gè)別名,方便書寫。 語法:
type 別名 = 類型 type s = string // 定義 const str1:s = 'abc' const str2:string = 'abc'
作用:
- 給類型起別名
- 定義了新類型
使用場景:給復(fù)雜的類型起個(gè)別名
type NewType = string | number let a: NewType = 1 let b: NewType = '1'
注意:別名可以是任意的合法字符串,一般首字母大寫
數(shù)組類型
語法:
// 寫法1: let 變量: 類型[] = [值1,...]: let numbers: number[] = [1, 3, 5] // numbers必須是數(shù)組,每個(gè)元素都必須是數(shù)字 // 寫法2: let 變量: Array<類型> = [值1,...] let strings: Array<string> = ['a', 'b', 'c'] // strings必須是數(shù)組,每個(gè)元素都必須是字符串
函數(shù)
函數(shù)涉及的類型實(shí)際上指的是:函數(shù)參數(shù)和返回值的類型
定義單個(gè)函數(shù)
語法:
// 普通函數(shù) function 函數(shù)名(形參1: 類型=默認(rèn)值, 形參2:類型=默認(rèn)值,...): 返回值類型 { } // 聲明式實(shí)際寫法: function add(num1: number, num2: number): number { return num1 + num2 } // 箭頭函數(shù) const 函數(shù)名(形參1: 類型=默認(rèn)值, 形參2:類型=默認(rèn)值, ...):返回值類型 => { } const add2 = (a: number =100, b: number = 100): number =>{ return a + b } // 注意: 箭頭函數(shù)的返回值類型要寫在參數(shù)小括號(hào)的后面 add(1,'1') // 報(bào)錯(cuò)
統(tǒng)一定義函數(shù)格式
當(dāng)函數(shù)的類型一致時(shí),寫多個(gè)就會(huì)顯得代碼冗余,所以需要統(tǒng)一定義函數(shù)的格式 如下所示:
const add2 = (a: number =100, b: number = 100): number => { return a + b } function add1 (a:number = 100 , b: number = 200): number { return a + b } // 這里的 add1 和 add2 的參數(shù)類型和返回值一致, // 那么就可以統(tǒng)一定義一個(gè)函數(shù)類型 type Fn = (n1:number,n2:number) => number const add3 : Fn = (a,b)=>{return a+b } // 這樣書寫起來就簡單多啦
函數(shù)返回值類型void
在 ts 中,如果一個(gè)函數(shù)沒有返回值,應(yīng)該使用 void
類型
function greet(name: string): void { console.log('Hello', name) //}
可以用到void
有以下幾種情況
- 函數(shù)沒寫return
- 只寫了 return, 沒有具體的返回值
- return 的是 undefined
// 如果什么都不寫,此時(shí),add 函數(shù)的返回值類型為: void const add = () => {} // 如果return之后什么都不寫,此時(shí),add 函數(shù)的返回值類型為: void const add = () => { return } const add = (): void => { // 此處,返回的 undefined 是 JS 中的一個(gè)值 return undefined } // 這種寫法是明確指定函數(shù)返回值類型為 void,與上面不指定返回值類型相同 const add = (): void => {}
那么就有人好奇,既然return undefined,那么為什么不可以直接在返回值那里寫 :undefined 呢? 如果函數(shù)沒有指定返回值,調(diào)用結(jié)束之后,值是undefined的,但是不能直接聲明返回值是undefined
function add(a:number, b:number): undefined { // 這里會(huì)報(bào)錯(cuò) console.log(a,b) }
函數(shù)-可選參數(shù)
使用函數(shù)實(shí)現(xiàn)某個(gè)功能時(shí),參數(shù)可以傳也可以不傳。
例如:數(shù)組的 slice 方法,可以 slice()
也可以 slice(1)
還可以 slice(1, 3)
那么就可以定義可選參數(shù) 語法:
//可選參數(shù):在可選參數(shù)名的后面添加 ?(問號(hào)) function slice (a?: number, b?: number) { // ? 跟在參數(shù)名字的后面,表示可選的參數(shù) // 注意:可選參數(shù)只能在 必須參數(shù)的后面 // 如果可選參數(shù)在必選參數(shù)的前面,會(huì)報(bào)錯(cuò) console.log(111); } slice() slice(1) slice(1,2) }
可選和默認(rèn)值的區(qū)別
相同點(diǎn): 調(diào)用函數(shù)時(shí),可以少傳參數(shù)
區(qū)別:設(shè)置了默認(rèn)值之后,就是可選的了,不寫就會(huì)使用默認(rèn)值; 可選的參數(shù)一定有值。
注意:它們不能一起使用。優(yōu)先使用默認(rèn)值
對象類型-單獨(dú)使用
格式: 方法有兩種寫法: 普通函數(shù) 和 箭頭函數(shù)
const 對象名: { 屬性名1:類型1, 屬性名2?:類型2, 方法名1(形參1: 類型1,形參2: 類型2): 返回值類型, 方法名2:(形參1: 類型1,形參2: 類型2) => 返回值類型 } = { 屬性名1: 值1,屬性名2:值2 }
對象類型-類型別名
// 創(chuàng)建類型別名 type Person = { name: string, age: number sayHi(): void } // 使用類型別名作為對象的類型: let person: Person = { name: '小花', age: 18 sayHi() {} }
接口
當(dāng)一個(gè)對象類型被多次使用時(shí),有如下兩種方式來來描述對象的類型,以達(dá)到復(fù)用的目的:
- 類型別名,type
- 接口,interface
語法:
interface 接口名 {屬性1: 類型1, 屬性2: 類型2} // 這里用 interface 關(guān)鍵字來聲明接口 interface IGoodItem { // 接口名稱(比如,此處的 IPerson),可以是任意合法的變量名稱,推薦以 `I` 開頭 name: string, price: number, func: ()=>string } // 聲明接口后,直接使用接口名稱作為變量的類型 const good1: IGoodItem = { name: '手表', price: 200, func: function() { return '看時(shí)間' } } const good2: IGoodItem = { name: '手機(jī)', price: 2000, func: function() { return '打電話' } }
接口和類型 的區(qū)別 interface
(接口)和 type
(類型別名)的對比:
- 相同點(diǎn):都可以給對象指定類型
- 不同點(diǎn):
- 接口,只能為對象指定類型。它可以繼承。
- 類型別名,不僅可以為對象指定類型,實(shí)際上可以為任意類型指定別名
先有的 interface
,后有的 type
,推薦使用 type
// 接口的寫法------------- interface IPerson { name: string, age: number } const user1:IPerson = { name: 'a', age: 20 } // type的寫法------------- type Person = { name: string, age: number } const user2:Person = { name: 'b', age: 20 }
接口繼承
如果兩個(gè)接口之間有相同的屬性或方法,可以將公共的屬性或方法抽離出來,通過繼承來實(shí)現(xiàn)復(fù)用 語法:
interface 接口2 extends 接口1 { 屬性1: 類型1, // 接口2中特有的類型 } interface a { x: number; y: number } // 繼承 a // 使用 extends(繼承)關(guān)鍵字實(shí)現(xiàn)了接口 interface b extends a { z: number } // 繼承后,b 就有了 a 的所有屬性和方法(此時(shí),b 同時(shí)有 x、y、z 三個(gè)屬性)
元組
元組是一種特殊的數(shù)組。有兩點(diǎn)特殊之處
它約定了的元素個(gè)數(shù)
它約定了特定索引對應(yīng)的數(shù)據(jù)類型
舉個(gè)例子: 就拿 react 里面的 useState來舉例:
function useState(n: number): [number, (number)=>void] { const setN = (n1) => { n = n1 } return [n, setN] } const [num ,setNum] = useState(10)
字面量類型
例如下面的代碼
let str1 = 'hello TS' const str2 = 'hello TS'
大家可以猜一下,str1 是什么類型的,str2 是什么類型?不要偷偷看答案哦。
這里是正確答案: str1 的類型為 string
類型,str2 的類型為 Hello TS
類型
這是為啥呢?
- str1 是一個(gè)變量(let),它的值可以是任意字符串,所以類型為:string
- str2 是一個(gè)常量(const),它的值不能變化只能是 'hello TS',所以,它的類型為:'hello TS'
注意:此處的 'Hello TS',就是一個(gè)字面量類型,也就是說某個(gè)特定的字符串也可以作為 TS 中的類型
這時(shí)候就有人好奇了,那字面量類型有啥作用呢? 字面量類型一般是配合聯(lián)合類型一起使用的, 用來表示一組明確的可選值列表。 例如下面的例子:
type Gender = 'girl' | 'boy' // 聲明一個(gè)類型,他的值 是 'girl' 或者是 'boy' let g1: Gender = 'girl' // 正確 let g2: Gender = 'boy' // 正確 let g3: Gender = 'man' // 錯(cuò)誤
可以看到會(huì)有提示,明確告訴你只能選這兩種。媽媽再也不用擔(dān)心寫錯(cuò)啦
枚舉
枚舉(enum)的功能類似于字面量類型+聯(lián)合類型組合的功能,來描述一個(gè)值,該值只能是 一組命名常量 中的一個(gè)。 在沒有 type 的時(shí)候,大家都是用枚舉比較多的,現(xiàn)在比較少了。 語法:
enum 枚舉名 { 可取值1, 可取值2,.. } // 使用格式: 枚舉名.可取值
注意:
- 一般枚舉名稱以大寫字母開頭
- 枚舉中的多個(gè)值之間通過
,
(逗號(hào))分隔 - 定義好枚舉后,直接使用枚舉名稱作為類型注解
枚舉也分?jǐn)?shù)值枚舉 和 字符串枚舉。 數(shù)值枚舉: 默認(rèn)情況下,枚舉的值是數(shù)值。默認(rèn)為:從 0 開始自增的數(shù)值 當(dāng)然,也可以給枚舉中的成員初始化值
enum Direction { Up = 10, Down, Left, Right } // Down -> 11、Left -> 12、Right -> 13 enum Direction { Up = 2, Down = 3, Left = 8, Right = 16 }
字符串枚舉:
enum Direction { Up = 'UP', Down = 'DOWN', Left = 'LEFT', Right = 'RIGHT' }
注意:字符串枚舉沒有自增長行為,因此,字符串枚舉的每個(gè)成員必須有初始值
any 類型
any: 任意的。當(dāng)類型設(shè)置為 any 時(shí),就取消了類型的限制。 例如:
let obj: any = { x: 0 } obj.bar = 100 obj() // obj 可以是任意類型 const n: number = obj
使用any的場景
- 函數(shù)就是不挑類型。 例如,
console.log()
; 定義一個(gè)函數(shù),輸入任意類型的數(shù)據(jù),返回該數(shù)據(jù)類型 - 臨時(shí)使用 any 來“避免”書寫很長、很復(fù)雜的類型
還有一種隱式 any,有下面兩種情況會(huì)觸發(fā)
- 聲明變量不提供類型也不提供默認(rèn)值
- 定義函數(shù)時(shí),參數(shù)不給類型
注意:不推薦使用 any!這會(huì)讓 TypeScript 變?yōu)?“AnyScript”(失去 TS 類型保護(hù)的優(yōu)勢)
類型介紹這邊就不一一展開了,更多介紹請看查閱官網(wǎng)。TypeScript官方文檔
以上就是TypeScript保姆級教程的詳細(xì)內(nèi)容,更多關(guān)于TypeScript教程的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
TypeScript中的數(shù)據(jù)類型enum?type?interface基礎(chǔ)用法示例
這篇文章主要為大家介紹了TypeScript中的數(shù)據(jù)類型enum?type?interface基礎(chǔ)用法示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08TypeScript使用noImplicitAny實(shí)戰(zhàn)解析
這篇文章主要為大家介紹了TypeScript使用noImplicitAny實(shí)戰(zhàn)解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08TypeScript手寫一個(gè)簡單的eslint插件實(shí)例
這篇文章主要為大家介紹了TypeScript手寫一個(gè)簡單的eslint插件實(shí)例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02TypeScript防抖節(jié)流函數(shù)示例詳解
這篇文章主要為大家介紹了TypeScript防抖節(jié)流函數(shù)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08