TS珠峰 001【學習筆記】

課程大綱

  • 建置 TypeScript 開發環境。
  • 掌握 TypeScript 的基礎類型、聯集類型和交集類型。
  • 詳細說明型別斷言的作用和用法。
  • 掌握 TypeScript 中函式、類別的型別宣告方式。
  • 掌握型別別名、介面的作用和定義。
  • 掌握泛型(Generics)的應用場景,熟練應用泛型。
  • 靈活運用條件類型、映射類型與內建類型。
  • 建立和使用自訂類型。
  • 理解命名空間(Namespace)、模組(Module)的概念及使用場景。
  • 詳細說明 TS 中的型別保護(Type Guard)、裝飾器(Decorator)。
  • 巧妙運用型別推導和簡化程式碼。
  • 深入理解 TypeScript 型別層級系統。
  • 詳細說明函式的變型(Variance)與逆變(Contravariance)。
  • 深入研究 infer 的用法與技巧。
  • 詳細探究符號類型。
  • 靈活編寫與運用型別宣告檔案,擴展 TypeScript 的型別系統。
  • 掌握 TS 中型別檔案查找規則。
  • 深刻使用裝飾器,運用反射元資料(Reflection Metadata)擴展裝飾器的功能,實現控制反轉(Inversion of Control, IoC)、依賴注入(Dependency Injection, DI)。
  • 深度解析 TSConfig 設定檔。
  • TS 型別體操

ts基礎

目前大部分企業的中大型前端專案都採用了 Typescript,那麼為什麼我們需要它?

JavaScript 的核心特點就是靈活,但隨著專案規模的增大,靈活反而增加開發者的心智負擔。例如在程式碼中一個變數可以被賦予字串、布林值、數字,甚至是函式,這樣就充滿了不確定性。而且這些不確定性可能需要在程式碼執行的時候才能被發現,所以我們需要型別的約束。

當然不可否認的是有了型別的加持多少會影響開發效率,但是可以讓大型專案更加健壯。

  • Typescript 更像後端 JAVA,讓 JS 可以開發大型企業應用;
  • TS 提供的型別系統可以幫助我們在撰寫程式碼時提供豐富的語法提示;
  • 在編寫程式碼時會對程式碼進行型別檢查,從而避免很多線上錯誤;

越來越多的專案開始擁抱 TS 了,典型的 Vue3、Pinia、第三方工具庫、後端 NodeJS 等。我們也經常為以上程式設計擁有更好的支援去編寫 .d.ts 檔案。

1. ts是一門語言

  1. ts 是 js 的一個超集,擴展了語法,添加了靜態型別支援以及其他一些新特性。

環境配置

全域安裝

npm install typescript -g
# 我們可以用 tsc 來把 ts 轉成 js
# 我們要把什麼轉換成什麼,所以我們要先生成一個設定
# 在目前專案下建立一個設定檔 tsc --init
# --watch
tsc --init
# 外掛程式 code runner 這個外掛程式需要額外安裝一個 ts-node 的套件
 npm init -y
 npm install typescript rollup -D
 npm install rollup-plugin-typescript -D
 npm i @rollup/plugin-node-resolve rollup-plugin-serve -D
#  rollup.config.js
# error lens 外掛程式

學習ts就是學習型別,ts的型別分類(DOM,Promise,原始方法)基礎類型,
ts 中:後面的都是型別 = 後面的都是值
ts 一切從安全的角度出發,看能不能賦值,就看安全不安全
ts 還有自動的型別推導,不用見到變數就寫型別,而是推斷的不正確,我們才需要自己編寫。

基礎類型

let abc: string = 'Hello World';
console.log(abc);

let name = 'John Doe'; // 目前模組中,作用域隔離
let age = 20;
let handsome: boolean = true;
// 原始類似識別碼都是小寫的,而類別名稱都是大寫的,它描述的實例(都是物件)
// 型別註解:告訴 TS 變數的型別
// 型別推斷:TS 會自動嘗試分析變數的型別
// 型別註解優先級高於型別推斷
// 型別註解:變數名: 型別 = 值
// 型別推斷:變數名 = 值
let s1: string = 'Hello World';
let s2: String = new String('Hello World');
let s3: String = 'Hello World'; // 會自動轉換為物件
// 陣列宣告
let arr1: number[] = [1, 2, 3];
let arr2: Array<number> = [1, 2, 3];
// 元組(Tuple):固定長度的陣列
let tuple: [string, number] = ['Hello', 123];
// 元組的越界問題
// tuple[2] = 'World'; // 會報錯
let tuple2: readonly [string, number, boolean] = ['Hello', 123, true];
// tuple2[0] = 'World'; // 會報錯
export { name };

列舉(自帶型別的物件)

let abc: string = 'Hello World';
console.log(abc);

let name = 'John Doe'; // 目前模組中,作用域隔離
let age = 20;
let handsome: boolean = true;
// 原始類似識別碼都是小寫的,而類別名稱都是大寫的,它描述的實例(都是物件)
// 型別註解:告訴 TS 變數的型別
// 型別推斷:TS 會自動嘗試分析變數的型別
// 型別註解優先級高於型別推斷
// 型別註解:變數名: 型別 = 值
// 型別推斷:變數名 = 值
let s1: string = 'Hello World';
let s2: String = new String('Hello World');
let s3: String = 'Hello World'; // 會自動轉換為物件
// 陣列宣告
let arr1: number[] = [1, 2, 3];
let arr2: Array<number> = [1, 2, 3];
// 元組:固定長度的陣列
let tuple: [string, number] = ['Hello', 123];
// 元組的越界問題
// tuple[2] = 'World'; // 會報錯
let tuple2: readonly [string, number, boolean] = ['Hello', 123, true];
// tuple2[0] = 'World'; // 會報錯

// 列舉(Enum) 自帶型別的物件,自動增長
enum USER_ROLE {
  USER,
  ADMIN = 6,
  MANAGER,
  OTHER = 'other', // 異構列舉
}
/*
  USER = 0,
  ADMIN = 6,
  MANAGER = 7,
*/
console.log(USER_ROLE.USER); // 0
// 如果不需要物件可以直接採用常數列舉
const enum USER_ROLE2 {
  USER,
  ADMIN,
  MANAGER,
}
console.log(USER_ROLE2.USER); // 0
export { name };

null 和 undefined

// 嚴格模式下,不允許使用 any 型別
// null 和 undefined 是任何型別的子型別
let x: number | null | undefined = 1;
// let y: number = undefined; // 會報錯
// let z: number = null; // 會報錯
// strict:false 可以使用 any 型別

never類型

永遠不

// never 型別 它是任何型別的子型別,也可以賦值給任何型別
// never 型別的變數只能被賦值為 never 型別
function fn1(): never {
  throw new Error('報錯了');
}
// 型別保護(Type Guard),保障程式的不缺失
// never 是永遠到達不了的終點
function fn2(): never {
  while (true) {}
}
function validate(x: never) {
  console.log(x);
}
// 針對不同的型別做不同的處理
function fn3(x: number | string | boolean) {
  // 類似有收斂的作用
  if (typeof x === 'number') {
    console.log(x.toFixed(2));
    return;
  }
  if (typeof x === 'string') {
    console.log(x.trim());
    return;
  }
  if (typeof x === 'boolean') {
    console.log(x.valueOf());
    return;
  }
  //守衛語句
  validate(x); // 如果型別不匹配,會報錯 這個邏輯應該是永遠不會執行的,所以上面還是有沒覆蓋到的邏輯(要添加 boolean 型別的判斷)
}

object的類型

// object 型別 object {} Object
let obj: object = { name: 'John Doe' };
// obj.name = 'Jane Doe'; // 會報錯
// 小寫的 object 是物件型別,大寫的 Object 是物件的建構函式 

! 號非空斷言

聯集類型

// 一般我們會基於額外的型別來擴展定義型別,有點類似列舉
type Direction = "up" | "down" | "right" | "left"
let direction :Direction = "left"
// type 和 interface 的區別
type women =
  | {
      wealthy: true;
      waste: string;
    }
  | {
      wealthy: false;
      norality: string;
    };
// 是富人一定不是節儉的人,是節儉的人一定不是富人

可以利用聯集類型來做到屬性之間的互斥

斷言

斷言有可能出問題,出問題後果自負

type women =
| {
wealthy: true;
waste: string;
}
| {
wealthy: false;
norality: string;
};
// 是富人一定不是節儉的人,是節儉的人一定不是富人(類比約定,不嚴謹)
// 斷言 把某個型別斷言為已經存在的一種型別
let ele = document.getElementById('app');
ele!.innerHTML = 'Hello World'; // 繞過 TS 的型別檢查 ele

主題測試文章,只做測試使用。發佈者:Walker,轉轉請注明出處:https://walker-learn.xyz/archives/4409

(0)
Walker的頭像Walker
上一篇 2025年3月8日 02:11
下一篇 2025年3月27日 15:01

相關推薦

  • 深入理解ES6 003【學習筆記】

    函數參數預設值,以及一些關於 arguments 物件,如何使用運算式作為參數、參數的暫時性死區。 以前設定預設值總是利用在含有邏輯或運算子的運算式中,前一個值是 false 時,總是回傳後面那個值,但如果我們給參數傳入 0 時,就會有些麻煩。 需要去驗證一下型別 function makeRequest(url,timeout,callback){ timeout = t…

    個人 2025年3月8日
    1.2K00
  • 深入理解ES6 001【學習筆記】

    區塊作用域繫結 之前的變數宣告 `var` 無論在哪裡宣告,都會被視為作用域頂部宣告。由於函式是一等公民,因此順序通常是 `function 函式名稱()`、`var 變數`。 區塊宣告 區塊宣告用於宣告在指定區塊的作用域之外無法存取的變數。區塊作用域存在於: 函式內部 區塊中(字元 `{` 和 `}` 之間的區域) 暫時性死區 JavaScript 引擎在掃描程式碼發現變數宣告時,要麼會將它們提升至作…

    個人 2025年3月8日
    1.6K00
  • 熱愛運動,挑戰極限,擁抱自然

    熱愛 在這個快節奏的時代,我們被工作、生活的壓力所包圍,常常忽略了身體的需求。而運動,不只是一種健身方式,更是一種釋放自我、挑戰極限、與自然共舞的生活態度。無論是滑雪、攀岩、衝浪,還是跑步、騎行、瑜伽,每一種運動都能讓我們找到內心的激情,感受到生命的躍動。 運動是一場自我挑戰。挑戰極限,不只是職業運動員的專屬,而是每一個熱愛運動的人都可以追求的目標。它可…

    個人 2025年2月26日
    1.3K00
  • Go 工程師體系課 009【學習筆記】

    其他一些功能 個人中心 收藏 管理收貨地址(增刪改查) 留言 複製inventory_srv--> userop_srv 查詢替換所有的inventory Elasticsearch 深度解析文件 1. 什麼是Elasticsearch Elasticsearch是一個基於Apache Lucene建構的分散式、RESTful搜尋和分析引擎,能夠快速地…

    個人 2025年11月25日
    24100
  • 深入理解ES6 008【學習筆記】

    迭代器(Iterator)和產生器(Generator)這項新特性對於高效的資料處理而言是不可或缺的,你也會發現在語言的其他特性中也都有迭代器的蹤影:新的 for-of 迴圈、展開運算子 (...)、甚至連非同步程式設計都可以使用迭代器。 迭代器是一種特殊的物件,它具有一些專門為迭代過程設計的專有介面,所有的迭代器物件都有一個 next() 方法,每次呼叫都傳回一個結果對…

    個人 2025年3月8日
    1.1K00
歡迎🌹 Coding never stops, keep learning! 💡💻 光臨🌹