學(xué)習(xí)筆記(五)——TypeScript 語(yǔ)言

強(qiáng)類型與弱類型(類型安全維度)

語(yǔ)言層面限制

  • 強(qiáng)類型:不允許任意的數(shù)據(jù)隱式類型轉(zhuǎn)換
    • 在編碼階段就能提示類型錯(cuò)誤,可以更早暴露錯(cuò)誤
    • 可以提高代碼效率和準(zhǔn)確性(可以提供更準(zhǔn)確的智能提示)
    • 使重構(gòu)更便捷可靠
    • 可以減少不必要的類型判斷
  • 弱類型:允許任意的數(shù)據(jù)隱式類型轉(zhuǎn)換
    • 只能在代碼運(yùn)行階段才能發(fā)現(xiàn)問題
  • JavaScript是弱類型語(yǔ)言,Python是強(qiáng)類型語(yǔ)言

靜態(tài)類型與動(dòng)態(tài)類型(類型檢查維度)

  • 靜態(tài)類型:變量類型在聲明時(shí)確定,之后不允許再修改
  • 動(dòng)態(tài)類型:變量在運(yùn)行階段才能確定,且可以進(jìn)行修改
  • JavaScript是動(dòng)態(tài)類型語(yǔ)言,Python是動(dòng)態(tài)類型語(yǔ)言

解釋型與編譯型

  • 解釋型:代碼運(yùn)行時(shí)解析執(zhí)行(腳本語(yǔ)言)
  • 編譯型:需要預(yù)先編譯,再執(zhí)行編譯輸出的可執(zhí)行文件

JavaScript類型系統(tǒng)特征

JavaScript是動(dòng)態(tài)類型 弱類型 解釋型腳本語(yǔ)言

Flow

由Facebook于2014年推出的JavaScript的類型檢查器

  • 安裝

    • yarn add flow-bin --dev
    • yarn flow init 初始化flow并生成配置文件 .flowconfig
  • 使用

    • 在JS文件開頭添加注釋 //@flow
    • 在相應(yīng)的變量、參數(shù)后添加類型注解(冒號(hào)及類型)
    • 執(zhí)行 yarn flow 檢查
      • 會(huì)啟動(dòng)后臺(tái)服務(wù)監(jiān)控JS文件
    • 執(zhí)行 yarn flow stop 停止后臺(tái)服務(wù)
  • 編譯移除類型注解

    • flow-remove-types

      • yarn add flow-remove-types --dev 安裝
      • yarn flow-remove-types src -d dist 指定路徑輸出編譯移除后的JS文件
    • babel

      • yarn add @babel/core @babel/cli @babel/present-flow 安裝

      • 添加配置文件.babelrc

        {
            "presents": ["@babel/present-flow"]
        }
        
      • yarn babel src -d dist 指定路徑輸出編譯移除后的JS文件

  • 開發(fā)工具插件

    • VSCode插件:flow-language-support
    • 其他IDE插件支持情況查看flow官網(wǎng)的編輯器支持
  • flow類型推斷

    • 可以根據(jù)代碼實(shí)際使用情況自行推斷變量的類型,而可以不指明類型注解
  • flow類型注解

    • 在相應(yīng)的變量、參數(shù)后添加冒號(hào)及類型
  • flow的類型

    • 原始類型
      • string
      • number
      • boolean
      • null
      • undefined
        • 使用void表示
      • symbol
    • 數(shù)組類型
      • Array<number>
      • number []
      • [string, number] :元組
    • 對(duì)象類型
      • { foo?: string, bar: number }
        • 限制必須存在特定屬性,并限定該屬性的類型
        • 屬性名加問號(hào),表示該屬性可選,如果存在該屬性,則屬性類型必須為指定的類型
      • { [string]: string }
        • 限制對(duì)象key-value鍵值對(duì)類型,不限制屬性數(shù)量
    • 函數(shù)類型
      • (string, number) => void
        • 指定參數(shù)及返回值類型
    • 特殊類型
      • 字面量類型:a: 'foo' = 'foo'
        • 限定變量值只能是特定值
      • 聯(lián)合類型:使用 | 分隔多個(gè)類型
        • 字面量類型聯(lián)合:type: 'success' | 'warning' | 'danger' = 'success'
          • 限定只能是特定可選值之一
        • 類型聯(lián)合:a: string | number = 100
          • 限定只能是可選類型之一
      • 類型別名
        • type StringNumber = string | number
        • a: StringNumber = 'string'
      • maybe類型
        • 類型前加問號(hào) a: ?number = undefined
        • 等同于 a: number | null | void
    • Mixed與Any
      • 可以接收任意類型
      • Mixed:強(qiáng)類型
        • 雖然可以接收任意類型,但是需要先明確變量是什么類型,才能進(jìn)行相應(yīng)的使用
      • Any:弱類型
        • 接收任意類型,并可以任意進(jìn)行使用
        • 主要為了用來(lái)兼容未進(jìn)行強(qiáng)類型校驗(yàn)的老代碼
  • 運(yùn)行環(huán)境API

    • ES定義類型之外的運(yùn)行環(huán)境API類型

TypeScript

TypeScript是JavaScript的超集,在JavaScript基礎(chǔ)上擴(kuò)展了類型系統(tǒng)ES6+新特性

  • 優(yōu)點(diǎn):

    • 類型系統(tǒng)使代碼可靠性更高,同時(shí)可以使用ES6+新特性
    • 兼容性好,可以在任何使用JavaScript開發(fā)的環(huán)境使用TypeScript
    • 生態(tài)健全、完善
    • 漸進(jìn)式,可以只使用部分特性
  • 缺點(diǎn):

    • 增加了很多概念,例如:接口、枚舉、泛型
    • 需要編寫大量類型聲明,對(duì)小型項(xiàng)目會(huì)增加開發(fā)成本
  • 安裝

    • yarn add typescript --dev
  • 執(zhí)行

    • yarn tsc typescript.ts
      • 編譯 typescript.ts 為 typescript.js 文件
      • 進(jìn)行類型檢查
      • 移除類型注解
      • 轉(zhuǎn)換ES6+語(yǔ)法為ES3語(yǔ)法
  • 配置文件

    • yarn tsc --init 初始化創(chuàng)建配置文件 tsconfig.json
    • 配置項(xiàng)
      • target
        • 指定轉(zhuǎn)換為什么版本的ES標(biāo)準(zhǔn)代碼
        • 不設(shè)置默認(rèn)es3,配置文件默認(rèn)es5,其他可選 es2015/es2016/es2017/...
      • module
        • 模塊化標(biāo)準(zhǔn)
        • 默認(rèn)commonjs、其他可選 amd/umd/es2015/es2020/...
      • sourceMap
        • 源代碼映射,生成sourceMap,便于代碼調(diào)試
      • outDir
        • 指定編譯結(jié)果輸出目錄
        • 可以配置dist
      • lib
        • 指定標(biāo)ts準(zhǔn)庫(kù)(ES對(duì)應(yīng)版本內(nèi)置對(duì)象的聲明文件),接收一個(gè)數(shù)組
  • rootDir
    + 指定代碼根目錄
    + 可以配置src
    + strict
    + 開啟嚴(yán)格模式

    • 使用 yarn tsc 直接運(yùn)行
  • 原始類型

    • string
      • const a: string = 'hello'
      • 非嚴(yán)格模式可以是null或undefined
    • number
      • const b: number = 123
      • 包含 NaN Infinity
      • 非嚴(yán)格模式可以是null或undefined
    • boolean
      • const c: boolean = true
      • 非嚴(yán)格模式可以是null或undefined
    • void
      • const d: void = undefined
      • 標(biāo)記函數(shù)返回類型
      • 非嚴(yán)格模式可以是null
    • null
      • const e: null = null
    • undefined
      • const f: undefined = undefined
    • symbol
      • const g: symbol = Symbol()
      • 需要配置target: es2015以上,或者配置lib引入es2015標(biāo)準(zhǔn)庫(kù)
  • 強(qiáng)制使用中文顯示錯(cuò)誤消息

    • yarn tsc --locale zh-CN
    • 修改VSCode setting中相關(guān)的配置
    • 建議還是使用英文方式顯示,便于問題查詢定位
  • 作用域問題

    • 全局作用域下同名變量不能重復(fù)定義,可以放到函數(shù)作用域中,或者添加export {} 放到模塊作用域下
  • Object類型

    • const foo: object = {} // [] // function() {} 可以接受數(shù)組、函數(shù)、對(duì)象
    • const obj: { name: string, value: number} = { name: 'hello', value: 123}
      • 強(qiáng)制對(duì)象類型的聲明,可以使用對(duì)象字面量 {} 的方式,同時(shí)可以限制允許出現(xiàn)的屬性
      • 使用接口定義更合適
  • 數(shù)組類型

    • const array: Array<number> = [1, 2, 3]
    • const array: number[] = [1, 2, 3]
  • 元組類型

    • 元組是一種明確元素?cái)?shù)量和類型的特殊數(shù)組
    • const tuple: [number, string] = [123, '456']
    • 可以用來(lái)在一個(gè)函數(shù)中返回多個(gè)返回值
  • 枚舉類型

    • enum關(guān)鍵字定義枚舉類型

      enum Status {
          valid = 0,
          invalid
      }
      
    • 枚舉值使用等號(hào)=賦值

    • 如果不指定枚舉值,則默認(rèn)從0開始,依次遞增

    • 如果指定枚舉值為數(shù)字,則默認(rèn)依次遞增

    • 如果指定一個(gè)枚舉值為字符串,則需要指定所有它之后的所有枚舉的初始的值

    • 枚舉類型會(huì)被編譯為雙向鍵值對(duì)對(duì)象,可以使用key獲得value,也可以使用value獲得key

      var Status;
      (function (Status) {
          Status[Status["valid"] = 0] = "valid";
          Status[Status["invalid"] = 1] = "invalid";
      })(Status || (Status = {}));
      
    • enum關(guān)鍵字前增加const時(shí)為常量枚舉,常量枚舉不可以使用枚舉值訪問枚舉的key

  • 函數(shù)類型

    • 函數(shù)聲明形式

      function say (name: string, value: number, ...rest: number[]) : string {
          return `hello ${name}`
      }
      
    • 函數(shù)表達(dá)式形式

      const said: (name: string, value: number, ...rest: number[]) => string = (name: string, value: number, ...rest: number[]): string => {
          return `hello ${name}`
      }
      

      函數(shù)表達(dá)式將函數(shù)賦值給一個(gè)變量,需要給變量一個(gè)函數(shù)類型,使用箭頭函數(shù)的形式

  • 任意類型

    • any類型
      • 不會(huì)進(jìn)行類型檢查
      • 用來(lái)兼容JS老代碼
      • 存在類型安全問題
  • 隱式類型推斷

    • 由typescript自行推斷變量的類型
    • 建議給每個(gè)變量添加明確的類型
  • 類型斷言

    • 當(dāng)typescript無(wú)法明確推斷變量的類型時(shí),可以使用as關(guān)鍵字告訴typescript變量是什么類型
    • 也可以使用 <number> 尖括號(hào)<類型>的方式,但跟jsx混合使用的時(shí)候,會(huì)跟html標(biāo)簽混淆,建議使用as
  • 接口

    • 使用interface關(guān)鍵字定義接口,用來(lái)約束對(duì)象的結(jié)構(gòu)

      interface Post {
          name: string
          value: number
          desc?: string
          readonly url: string   
      }
      
    • 屬性名后加問號(hào),表示可選屬性,可選屬性外的其他屬性必須存在

    • 屬性名前加readonly關(guān)鍵字,表示只讀屬性,初始化后不可修改

    • 不能包含接口定義外的其他屬性

  • 面向?qū)ο缶幊讨械母拍?,用?lái)描述具體對(duì)象的抽象成員

    ES6以前,使用構(gòu)造函數(shù)+原型的方式實(shí)現(xiàn)面向?qū)ο蟮念惻c繼承

    ES6以后,提供了標(biāo)準(zhǔn)化的class來(lái)定義類

    typescript增強(qiáng)了class的相關(guān)語(yǔ)法(訪問修飾符、抽象類等)

    • 基本使用

      • class關(guān)鍵字定一個(gè)一個(gè)類

      • 在類中聲明屬性,并初始化(定義時(shí)賦值,或在構(gòu)造函數(shù)constructor中初始化)

        class Person {
            name: string
            age: number = 18
            constructor(name: string, age: number) {
                this.name = name
            }
        }
        
    • 訪問修飾符

      控制類中屬性和方法的訪問級(jí)別

      • public: 默認(rèn)
      • private: 無(wú)法被類的實(shí)例訪問
        • 如果constructor被private修飾,將不能使用new實(shí)例化
      • protected: 無(wú)法被類的實(shí)例訪問,可以在子類中訪問
    • 只讀屬性

      • readonly關(guān)鍵字修飾類的屬性
      • 只能在定義或者構(gòu)造函數(shù)中初始化,之后不能被修改
    • 類與接口

      • 同樣使用interface定義接口

      • 在interface中定義類的方法,但不提供實(shí)現(xiàn)

      • class使用implements關(guān)鍵字實(shí)現(xiàn)一個(gè)或多個(gè)接口,必須包含接口中定義的方法的實(shí)現(xiàn)

        interface Eat {
            eat(food: string): void
        }
        interface Run {
            run(speed: number): void
        }
        class Dog implements Eat, Run {
            eat(food: string) {
                console.log(food)
            }
            run(speed: number) {
                console.log(speed)
            }
        }
        
    • 抽象類

      • 使用abstract關(guān)鍵字定義抽象類

        • 抽象類不能被new實(shí)例化,只能被繼承
      • 使用abstract關(guān)鍵字定義抽象類的抽象方法

        • 抽象方法不能具有實(shí)現(xiàn)
        • 子類繼承后必須實(shí)現(xiàn)抽象方法
        abstract class Animal {
            eat(food: string): void {
                console.log(food)
            }
            abstract run(speed: number): void
        }
        
        class Cat extends Animal {
            run(speed: number): void {
        
            }
        }
        const cat = new Cat()
        cat.eat('food')
        
    • 泛型

      • 函數(shù)定義后使用<T>定義泛型,參數(shù)的類型可以被指定為T

      • 函數(shù)使用時(shí)在函數(shù)名后使用<類型>指明具體的類型,以此使函數(shù)在使用時(shí)可以傳入不同類型的參數(shù)

        function hey<T>(value: T) {
            console.log(value)
        }
        hey<string>('123')
        hey<number>(123)
        
    • 類型聲明

      • declare關(guān)鍵字進(jìn)行類型聲明
      • 使用第三方庫(kù)時(shí),如果沒有提供類型聲明文件,需要安裝相應(yīng)的類型聲明模塊
      • 類型聲明模塊應(yīng)該是開發(fā)依賴
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容