首頁 > 軟體

詳解TypeScript使用及型別宣告檔案

2022-06-07 14:02:09

簡介

宣告檔案是以.d.ts為字尾的檔案,開發者在宣告檔案中編寫型別宣告,TypeScript根據宣告檔案的內容進行型別檢查。(注意同目錄下最好不要有同名的.ts檔案和.d.ts,例如lib.ts和lib.d.ts,否則模組系統無法只根據檔名載入模組)

為什麼需要宣告檔案呢?我們知道TypeScript根據型別宣告進行型別檢查,但有些情況可能沒有型別宣告:

  • 第三方包,因為第三方包打包後都是JavaScript語法,而非TypeScript,沒有型別。
  • 宿主環境擴充套件,如一些hybrid環境,在window變數下有一些bridge介面,這些介面沒有型別宣告。

Script 與 Vue3

參考連結(英文):vuejs.org/guide/types…

參考連結(中文):staging-cn.vuejs.org/guide/types…

vue3配合ts中,還需要額外安裝一個 vscode 外掛:Typescript Vue Plugin

defineProps 與 Typescript

目標:掌握defineProps如何配合ts使用

  • defineProps配合vue預設語法進行型別校驗(執行時宣告)
// 執行時宣告
defineProps({
  money: {
    type: Number,
    required: true
  },
  car: {
    type: String,
    required: true
  }
})
  • defineProps配合ts的泛型定義props型別校驗,這樣更直接
// 使用 ts 的泛型指定 props 型別
defineProps<{
  money: number
  car?: string
}>()
  • props 可以通過解構來指定預設值
<script lang="ts" setup>
// 使用ts的泛型指令props型別
const { money, car = '小黃車' } = defineProps<{
  money: number
  car?: string
}>()
</script>

如果提供的預設值需要在模板中渲染,需要額外新增設定

vuejs.org/guide/extra…

// vite.config.js
export default {
  plugins: [
    vue({
      reactivityTransform: true
    })
  ]
}

defineEmits 與 Typescript

目標:掌握 defineEmits 如何配合ts使用

  • defineEmits 配合執行時宣告
const emit = defineEmits(['change', 'update'])
  • defineEmits配合ts 型別宣告,可以實現更細粒度的校驗
const emit = defineEmits<{
  (e: 'changeMoney', money: number): void
  (e: 'changeCar', car: string): void
}>()

ref 與 Typescript

目標:掌握ref配合ts如何使用

  • 通過泛型指定value的值型別,如果是簡單值,該型別可以省略
const money = ref<number>(10)
// 推薦寫法,提供效率
const money = ref(10)
  • 如果是複雜型別,泛型指定
interface Todo {
  id: number
  content: string
  done: boolean
}
// 複雜型別需要指定結構,不能省略
const list = ref<Todo[]>([])
list.value.push({ id: 1, content: '吃飯', done: false })

computed 與 Typescript

目標:掌握computed配合typescript如何使用

  • 通過泛型可以指定computed計算屬性的型別,通常可以省略
const leftCount = computed<number>(() => {
  return list.value.filter((v) => v.done).length
})
console.log(leftCount.value)

事件物件 與 Typescript

目標:掌握事件處理常式配合typescript如何使用

const btn = (e: MouseEvent) => {
  mouse.value.x = e.pageX
  mouse.value.y = e.pageY
}
<h2 @click="btn($event)">根元件</h2>

模板 Ref 與 Typescript

目標:掌握ref操作DOM時如何配合Typescript使用

const imgRef = ref<HTMLImageElement | null>(null)
onMounted(() => {
  console.log(imgRef.value?.src)
})

如何檢視一個DOM物件的型別:通過控制檯進行檢視

document.createElement('img').__proto__

可選鏈操作符

**目標:**掌握js中的提供的可選鏈操作符語法

內容

  • 可選鏈操作符( ?. )允許讀取位於連線物件鏈深處的屬性的值,而不必明確驗證鏈中的每個參照是否有效。
  • 參考檔案:developer.mozilla.org/zh-CN/docs/…
let nestedProp = obj.first?.second;
console.log(res.data?.data)
obj.fn?.()

if (obj.fn) {
    obj.fn()
}
obj.fn && obj.fn()

// 等價於
let temp = obj.first;
let nestedProp = ((temp === null || temp === undefined) ? undefined : temp.second);

非空斷言-TS

目標:掌握ts中的非空斷言的使用語法

內容:

  • 如果我們明確的知道物件的屬性一定不會為空,那麼可以使用非空斷言 !
// 告訴 typescript, 明確的指定obj不可能為空
let nestedProp = obj!.second;
  • 注意:非空斷言一定要確保有該屬性才能使用,不然使用非空斷言會導致bug

TypeScript型別宣告檔案

基本介紹

今天幾乎所有的 JavaScript 應用都會引入許多第三方庫來完成任務需求。 這些第三方庫不管是否是用 TS 編寫的,最終都要編譯成 JS 程式碼,才能釋出給開發者使用。 我們知道是 TS 提供了型別,才有了程式碼提示和型別保護等機制。

但在專案開發中使用第三方庫時,你會發現它們幾乎都有相應的 TS 型別,這些型別是怎麼來的呢? 型別宣告檔案

  • 型別宣告檔案:用來為已存在的 JS 庫提供型別資訊

  • TS 中有兩種檔案型別:1 .ts 檔案 2 .d.ts 檔案

  • .ts 檔案:

    既包含型別資訊又可執行程式碼

    可以被編譯為 .js 檔案,然後,執行程式碼

    用途:編寫程式程式碼的地方

  • .d.ts 檔案:

    只包含型別資訊的型別宣告檔案

    不會生成 .js 檔案,僅用於提供型別資訊,在.d.ts檔案中不允許出現可執行的程式碼,只用於提供型別

    用途:為 JS 提供型別資訊

  • 總結:.ts 是 implementation(程式碼實現檔案);.d.ts 是 declaration(型別宣告檔案)

  • 如果要為 JS 庫提供型別資訊,要使用 .d.ts 檔案

內建型別宣告檔案

  • TS 為 JS 執行時可用的所有標準化內建 API 都提供了宣告檔案
  • 比如,在使用陣列時,陣列所有方法都會有相應的程式碼提示以及型別資訊:
const strs = ['a', 'b', 'c']
// 滑鼠放在 forEach 上檢視型別
strs.forEach
  • 實際上這都是 TS 提供的內建型別宣告檔案
  • 可以通過 Ctrl + 滑鼠左鍵(Mac:Command + 滑鼠左鍵)來檢視內建型別宣告檔案內容
  • 比如,檢視 forEach 方法的型別宣告,在 VSCode 中會自動跳轉到 lib.es5.d.ts 型別宣告檔案中
  • 當然,像 window、document 等 BOM、DOM API 也都有相應的型別宣告(lib.dom.d.ts)

第三方庫型別宣告檔案

  • 目前,幾乎所有常用的第三方庫都有相應的型別宣告檔案
  • 第三方庫的型別宣告檔案有兩種存在形式:1 庫自帶型別宣告檔案 2 由 DefinitelyTyped 提供。
  • 庫自帶型別宣告檔案:比如,axios
  • 檢視 node_modules/axios 目錄

解釋:這種情況下,正常匯入該庫,TS 就會自動載入庫自己的型別宣告檔案,以提供該庫的型別宣告。

  • 由 DefinitelyTyped 提供
  • DefinitelyTyped 是一個 github 倉庫,用來提供高質量 TypeScript 型別宣告
  • DefinitelyTyped 連結
  • 可以通過 npm/yarn 來下載該倉庫提供的 TS 型別宣告包,這些包的名稱格式為:@types/*
  • 比如,@types/react、@types/lodash 等
  • 說明:在實際專案開發時,如果你使用的第三方庫沒有自帶的宣告檔案,VSCode 會給出明確的提示
import _ from 'lodash'
// 在 VSCode 中,檢視 'lodash' 前面的提示
  • 解釋:當安裝 @types/* 型別宣告包後,TS 也會自動載入該類宣告包,以提供該庫的型別宣告
  • 補充:TS 官方檔案提供了一個頁面,可以來查詢 @types/* 庫
  • @types/* 庫

自定義型別宣告檔案

專案內共用型別

  • 如果多個 .ts 檔案中都用到同一個型別,此時可以建立 .d.ts 檔案提供該型別,實現型別共用。
  • 操作步驟:

    建立 index.d.ts 型別宣告檔案。

    建立需要共用的型別,並使用 export 匯出(TS 中的型別也可以使用 import/export 實現模組化功能)。

    在需要使用共用型別的 .ts 檔案中,通過 import 匯入即可(.d.ts 字尾匯入時,直接省略)。

為已有 JS 檔案提供型別宣告

  • 在將 JS 專案遷移到 TS 專案時,為了讓已有的 .js 檔案有型別宣告。
  • 成為庫作者,建立庫給其他人使用。
  • 演示:基於最新的 ESModule(import/export)來為已有 .js 檔案,建立型別宣告檔案。

型別宣告檔案的使用說明

  • 說明:TS 專案中也可以使用 .js 檔案。
  • 說明:在匯入 .js 檔案時,TS 會自動載入與 .js 同名的 .d.ts 檔案,以提供型別宣告。
  • declare 關鍵字:用於型別宣告,為其他地方(比如,.js 檔案)已存在的變數宣告型別,而不是建立一個新的變數。

    對於 type、interface 等這些明確就是 TS 型別的(只能在 TS 中使用的),可以省略 declare 關鍵字。

    對於 let、function 等具有雙重含義(在 JS、TS 中都能用),應該使用 declare 關鍵字,明確指定此處用於型別宣告。

let count = 10
let songName = '痴心絕對'
let position = {
  x: 0,
  y: 0
}
function add(x, y) {
  return x + y
}
function changeDirection(direction) {
  console.log(direction)
}
const fomartPoint = point => {
  console.log('當前座標:', point)
}
export { count, songName, position, add, changeDirection, fomartPoint }

定義型別宣告檔案

declare let count:number
declare let songName: string
interface Position {
  x: number,
  y: number
}
declare let position: Position
declare function add (x :number, y: number) : number
type Direction = 'left' | 'right' | 'top' | 'bottom'
declare function changeDirection (direction: Direction): void
type FomartPoint = (point: Position) => void
declare const fomartPoint: FomartPoint
export {
  count, songName, position, add, changeDirection, FomartPoint, fomartPoint
}

到此這篇關於TypeScript使用以及型別宣告檔案的文章就介紹到這了,更多相關TypeScript使用內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com