1. 程式人生 > 其它 >TypeScript的基本使用(1)

TypeScript的基本使用(1)

簡介

  • js
    • 優點:不容易報錯
    • 缺點:
      • ES6前使用面向物件比較麻煩(需要結合原型+建構函式);
      • 沒有變數型別,會根據值來定義資料型別;js的變數是動態型別--可能會導致後面做運算時因為值發生改變,資料型別不匹配可能導致不會報錯,只有當程式執行到才會報錯。
      • js定義函式時引數沒有型別的限制,我們可以在呼叫函式時傳任意資料型別,這樣就導致在執行某個語句後程序才出現報錯的情況
  • ts
    • 是微軟開發的,為了解決js所帶來的缺點,但不是為了替代js(因為js對於前端的影響非常大)
    • 引入了資料型別,讓js從動態語言轉成靜態語言。即變數宣告時可以指定型別,型別一旦執行不能發生變化,否則會提示報錯(但還是可以編譯,後期我們可以通過webpack配置解決)。
    • 目前情況下,ts檔案不能直接被JS解析器直接執行。即ts檔案不能在瀏覽器上直接執行
    • ts可以通過配置讓js變得嚴謹或者鬆散
    • ts中可以使用js中所有的語法

typescript編譯

預設情況下.ts檔案是不能直接在瀏覽器使用的,需要通過node中的typescript進行編譯生成js。

步驟:

  1. 下載並安裝Node.js
  2. 使用npm全域性安裝typescript
npm i -g typescript
  1. 建立hello.ts檔案,並編寫程式碼
let a:string = "hello typescript"
  1. 使用tsc命令進行編譯
tsc hello.tsc

基本型別

型別有:number、string、boolean、字面量、any、unknown、void、never、object、array、tuple、enum

用法:

let a:number = 20

字面量

let n1:10
n1 = 10
# n1 = 20 報錯

unknown型別和any型別

  • 可以將任意型別的值賦值給unknown型別或any型別的變數;
  • 可以將any型別的變數賦值可以任意型別的變數;但是不能將unknown型別的變數賦值給任意型別(any型別除外)的變數
  • 簡單理解為any會導致原本變數定義的資料型別不起作用了;或者理解為any權力最大,可以做任何的賦值操作。所以如果一個型別不確定時推薦使用unknown
let n1:unknown
let n2
n1 = 10
n1 = "hello"
n2 = 20
n2 = "ts"

let n3:string = "ok"
n3 = n2
# n3 = n1  這裡會報錯

型別斷言

有些情況下,變數的型別對於我們來說是很明確,但是TS編譯器卻並不清楚,此時,可以通過型別斷言來告訴編譯器變數的型別,一般用在變數設定為unknown型別時

let n1:unknown
let s = "hello"
n1 = "ts"
# s = n1   報錯

# 方式1: 變數 as 型別
s = n1 as string; 
# 方式2: <型別>變數
s = <string>n1

物件

let o :{name:string} = {name:'zs'}
# 下面會報錯
# let o: { name: string } = { name: 'zs', age: 20 }

# 屬性設定多個;propName是變數別名,可以隨意起
let o1:{name:string,[propName:string]:any} = {name:'ls',age:18}

函式

let sum: (n1: number, n2: number) => number

sum = function (n1, n2) {
  return n1 + n2
}

陣列

let arr1: string[];
arr1 = ['i','love','ts']
let arr2: Array<number>;
arr2 = [10,20,30]

元組

固定長度的陣列

let t1: [string,number]
t1 = ['ok',200]

列舉

enum Gender{
  Male,
  Female
}

let o:{name:string,gender:Gender}
o = {name:'莉莉',gender:Gender.Female}

其他

或者

# n1的值可以是10或者string
let n1: 10 | string
n1 = 'hello'
n1 = 10

並且

let j: { name: string } & { age: number };
j = {name: '孫悟空', age: 18};

編譯選項

自動編譯單個檔案

使用 -w 指令後,TS編譯器會自動監視檔案的變化,並在檔案發生變化時對檔案進行重新編譯。【-w,表示watch】

tsc -w hello.ts

自動編譯整個資料夾

tsconfig.json是ts編譯器的配置檔案,ts編譯器可以根據它的資訊來對程式碼進行編譯

  1. 在專案根目錄下建立空的tsconfig.json檔案
  2. 然後執行tsc -w命令會實時監控當前目錄以及子目錄下的所有檔案的變化,對.ts字尾的檔案進行自動編譯

編譯子選項

include

  • 預設情況下當前目錄以及子目錄下的所有檔案都會進行編譯,如果要對某幾個目錄下的檔案進行編譯的話,則需要指定此選項。
  • 預設值為:["**/*"]
// 對src、test目錄下的所有檔案以及所有子檔案都進行編譯
"include": ["src/**/*","test/**/*"]

exclude

  • 定義不需要進行編譯的目錄
"exclude":["node_modules"]

extends

  • 定義多個配置檔案,當配置檔案需要按結構進行分離時可採取此方式
// 會自動包含config目錄下的basic.json檔案
"extends": "./config/basic"

files

  • 指定被編譯的檔案列表
"files":["1.ts","2.ts","3.ts"]

compilerOptions

重點

  • 此選項包含多個子選項,用來完成對編譯的配置
target
  • 設定ts程式碼編譯的目標版本
  • 可選值:ES3(預設)、ES5、ES6/ES2015、ES7/ES2016、ES2017、ES2018、ES2019、ES2020、ESNext
"compilerOptions":{
  "target":"ES6"
}
outDir
  • 預設情況下,編譯後的js檔案會和ts檔案位於相同的目錄,設定outDir後可以改變編譯後文件的位置
"compilerOptions": {
    "outDir": "dist"
}
outFile
  • 預設情況下一個ts檔案對應編譯成一個js檔案,如果需要打包成一個js檔案的話則可以設定此選項
"compilerOptions":{
  "outFile":"dist/bundle.js"
}
allowJs
  • 預設情況下不對js檔案進行編譯,如果需要進行編譯的話則可以設定此選項
"compilerOptions":{
  "allowJs": true
}
removeComments
  • 預設情況下會對註釋進行打包輸出,如果在打包檔案中不想輸出註釋內容則可以設定此選項
"compilerOptions":{
  "removeComments": true
}
noEmit
  • 預設情況下會對程式碼進行編譯,可以看到編譯生成的檔案,如果不想編譯生成檔案則可以設定此選項
"compilerOptions":{
  "noEmit": true
}
module
  • 指定要使用的模組化規範
  • 可選值有:none, commonjs, amd, system, umd,es6, es2015, es2020, esnext
noEmitOnError
  • 預設情況下語法錯誤也能進行編譯,如果錯誤不想編譯則可以設定此選項
"compilerOptions":{
  "noEmitOnError": true,
}
strict
  • 開啟嚴格模式,開發中會開啟,讓程式更嚴謹
"compilerOptions":{
  "strict": true,
}

設定了嚴格模式後,會對程式碼進行空值的判斷。如果存在空值的可能則需進行下面的處理

let btn = document.querySelector("btn")
// 如果btn為空則不進行事件函式的處理
btn?.onclick=function(){
  alert('test')
}

Webpack使用TS[待驗證]

  • 通常情況下,實際開發中我們都需要使用構建工具對程式碼進行打包,TS也可以結合構建工具一起使用。
  • 簡單來說,使用webpack對ts進行編譯生成js。

使用步驟如下:

  1. 使用npm ini -y初始化專案
  2. 安裝開發時依賴
npm install -D webpack webpack-cli  typescript ts-loader
  1. 根目錄下建立webpack.config.js檔案
const path = require('path')

module.exports = {
  entry: './src/index.ts',
  output: {
    path: path.resolve(__dirname,'dist'),
    filename: 'bundle.js'
  },
  module:{
    rules:[
      {
        test:/\.ts$/,
        use:'ts-loader',
        exclude: /node-modules/
      }
    ]
  },
  /* 
  	預設情況下,xx.ts不能直接使用"import"和"export"的方式 載入或者匯出
    解決ts檔案可以使用"import"或"export"方式載入或匯出
  */
  resolve:{
    extensions: [".ts",".js"]
  }
}
  1. 建立tsconfig.json配置檔案,指定ts編譯時的規則
{
  "compilerOptions": {
    "module": "ES2015",
    "target": "ES2015",
    "strict": true
  }
}
  1. package.json中的script屬性配置打包命令
{
  "script":{
    "build": "webpack"
  }
}
  1. 執行打包命令
npm run build

注意

  • 在使用import匯入檔案時不能新增檔名字尾否則會報錯。比如: import {n1} from './a'

babel[待驗證]

  • JS中有不同的版本,比如:ES5,ES6,ES2020...等等。當我們採用新版本的JS去寫程式碼時,低版本的瀏覽器無法識別,所以需要有一種可以將新語法的轉換成舊版的,這樣才能讓低版本的瀏覽器去識別。

  • 其中tsconfig.jsoncompilerOptions屬性有target選項,我們可以指定編譯成js的版本,它只能做JS中簡單的語法轉換,但對於新增的技術它是不支援的(比如:ES6的Promise),這個時候就需要使用到babel可以相容更多的瀏覽器

  • babel的作用

    • 把新語法轉換成舊語法
    • 把新的類、物件轉換成低版本瀏覽器支援的類。
    • 為了讓程式碼有更好的相容性,可以在不同的瀏覽器中使用,使用babel來幫助我們解決相容性的問題

步驟:

  1. 安裝開發時依賴
cnpm i -D @babel/core  @babel/preset-env babel-loader core-js
  • @babel/core --核心庫
  • @babel/preset-env ---預設環境。我們需要相容不同的瀏覽器環境,這個模組裡面定義好了轉換的程式碼
  • babel-loader的作用是將 babel和webpack結合的一款工具
  • core-js的作用是模擬js的執行環境,讓老版本的瀏覽器可以使用到新標準的技術。裡面裝有所有相容新功能的程式碼,在開發中我們經常是按需載入
  1. webpack.config.js配置
module:{
  rules:[
    {
      test:/\.ts$/,
      use:[
        //多個loader進行處理,則use使用陣列的形式
        // 多個loader的執行順序是從後往前。
        // ts-loader的作用是將ts轉換為js;babel-loader的作用是將js轉換為低版本瀏覽器可識別的js程式碼
        // 如果loader需要詳細的配置,則將字串形式轉換為物件的形式
        {
          loader:"babel-loader",
          options:{
            // 設定預定義的環境【也就是假設你的程式碼是要在哪些環境下執行】
            presets:[
              [
                "@babel/preset-env",
                {
                  //指定瀏覽器的版本
                  targets:{
                    // 相容chrome的58版本
                    "chrome":"58",
                    "IE":"11"        //也就是說相容所有低版本的瀏覽器
                  },
                  //指定corejs的版本   【和當前安裝的版本一致即可】
                  "corejs": "3",
                  // 使用corejs的方式
                  "useBuiltIns": "usage"        //按需載入
                }
              ]
            ]
          }
        },
        "ts-loader"
      ]
    }
  ]
}
  1. 使用上述配置和不使用上述配置,然後設定tsconfig.json中的compilerOptions屬性的target屬性配置為ES2015(這個就是ES6版本),測試ts檔案中使用const定義變數的形式 是否在打包後的js檔案中轉換。

    • 不使用上述配置,打包後的js檔案中 const定義的變數【沒有】轉換成var宣告的變數

    • 使用上述配置,然後webpack配置targets中含有低版本的IE,那麼const定義的變數【會】轉換成var宣告的變數

    • 注意

      • 上面使用const等普通的ES6語法是沒有使用到corejs;當載入低版本瀏覽器不能識別的類或物件等情況時會使用到corejs中封裝的程式碼,這樣才能讓低版本瀏覽器識別(比如:Promise)。------corejs只有在下面配置後才起作用
      "corejs": "3",
      "useBuiltIns": "usage"
      
      • 上面使用corejs按需載入後可能還是在IE不能成功執行,因為起打包後生成的js是箭頭函式,IE不支援。babel可以將箭頭函式轉換為瀏覽器識別的函式。上面報錯是因為webpack打包後自帶生成箭頭函式來處理打包後的js,我們可以告訴webpack使用普通函式打包不要使用箭頭函式。webpack.config.js配置如下
      module.exports = {
        output: {
          environment:{
            arrowFunction: false
          }
        }
      }