【TS】學習總結

kernel_developer發表於2021-08-24

【TS】學習總結

01-TypeScript編譯環境

TypeScript全域性安裝

npm install typescript -g
tsc --version //檢視版本,安裝成功

TypeScript執行環境

  • 常規路徑

    tsc demo.ts//demo.ts -> demo.js
    執行js檔案
    
  • ts-node(類似於node執行js)

    npm install ts-node -g
    //ts-node依賴tslib、@types/node
    npm install tslib @types/node -g
    ts-node demo.ts
    
  • webpack工程環境

    ts-webpack -- coderwhy老師

    - mkdir demo & cd demo
    npm init
    npm install typescript
    tsc --init
    npm install webpack webpack-cli webpack-dev-server -D
    npm install ts-loader -D
    npm install html-webpack-plugin -D
    - 配置package.json
    - 配置webpack.config.js
    ...
    

02-TypeScript資料型別

資料定義語法

const/let/var name(: Type) = value;

不標明Type則會進行型別推導

基本資料型別

...

Array型別

推薦(TSLint):

const names1: string[] = ["why", "abc", "cba"];
const names2: Array<string> = ["why", "abc", "cba"];

陣列型別元素型別相同。

object型別

// 使用型別推斷
const obj = {
  name:"afs",
  age: 23
};

symbol型別&null型別&undefined型別

...


TypeScript新增資料型別

enum型別

enum Direction {
  EAST,
  WEST,
  NORTH,
  SOUTH,
}
const d1 = Direction.EAST; // 0
const d2 = Direction.NORTH; // 2
// 指定值,未賦值的依次遞增
enum Direction {
  EAST = 10,
  WEST = 20,
  NORTH,
  SOUTH = 40,
}
/*
console.log(Direction);
{
  '10': 'EAST',
  '20': 'WEST',
  '21': 'NORTH',
  '30': 'SOUTH',
  EAST: 10,
  WEST: 20,
  NORTH: 21,
  SOUTH: 30
}
*/
console.log(Direction[21]); // NORTH

tuple型別

相較於陣列,元素型別不同則為元組。

const num = [111, "sadfdsa"];
num.push(123)
num.push("asdfs") 
num // [ 111, 'sadfdsa', 123, 'asdfs' ]

any型別

相對於保留js特性的變數(型別不確定)。

如果需要某個變數的型別不固定,可以顯式定義any。

void型別

如果一個函式沒有返回值,那麼它的返回值型別就是void。

  • 函式不顯式定義返回型別,則會對返回值進行型別推導,沒有返回值則返回undefined
  • 如果定義為void,預設不能有返回值,❗但可以顯式返回undefined
  • 如果定義為any,可以返回任何型別
  • 如果定義為其他特定型別,則必須有返回值且型別相同,比如undefined則必須顯式返回undefined
function a(): undefined{
  console.log(1)
}// 報錯

never型別

never 表示永遠不會發生的型別。

如:一個從來不會有返回值的函式(死迴圈),一個總是會丟擲錯誤的函式。(一切不可能執行到的部分均可以限定為never型別)

function foo(x: string | number ): boolean {
  if (typeof x === 'string') {
    return true;
  } else if (typeof x === 'number') {
    return false;
  }

  // 如果 前面的判斷有遺漏 ,這會報錯:
  // - 不是所有條件都有返回值 (嚴格模式下)
  // - 或者檢查到無法訪問的程式碼
  // 但是由於 TypeScript 執行永遠不會被訪問的 `never` 型別
  // 你可能會用它來做安全或者詳細的檢查。
  const check: never = x;
}
// 如果有開發人員需要zx型別

unknown型別

unknown 型別含義類似於any

unknown 型別不能賦值給除了 unknownany 的其他任何型別,使用前必需顯式進行指定型別,或是在型別縮小情況下能夠隱式地進行型別推斷的情況。

函式型別

const func: (n: number, s: string) => void = function func(m: number, n: string): void{
	//code block
}

型別別名

type newType = number|string;

字面量型別

let m: 'message' = "message";
//m型別則為確定的'message'型別
m = 'other';//報錯

字面量推斷

function func(m: "a"|"b"|"c"){}
let a = "a";
func(a);//報錯
//reason: a: string,m需要字面量型別,即使a="a"可以避免a更改為其他字串
// => 改成
func(a as "a"); //或
const a = "a"; //或
const a = "a" as const;

03-TypeScript中函式

有一部分可見02-...[void型別]部分。

function func(m: type, n: type): type{
	//code block
}
// 如果引數type不寫會預設是any,返回值type會根據函式體返回值自動型別推斷

匿名函式會根據上下文自動推斷引數型別。

const array = [1, 2, 3];
array.forEach(item => {
	//code block
})
//此處item會上下文進行型別推斷: number

物件型別

function func(obj: {m: number, n: string}){}

可選型別

function func(m?: number){}
//m可選

聯合型別

function func(m: number|string){}
//m為其中型別之一
//使用前需要型別縮小或型別斷言

型別斷言as

將不確定的型別轉為更確定的型別。

//強制轉換
const s2n = ("string" as unknown) as number;
...

非空型別斷言!

function func(m?: string){
  return m.length;
}
//編譯報錯
//改成 => 逃過編譯階段報錯
function func(m?: string){
  return m!.length;
}

可選鏈

//上面程式碼可以改成
function func(m?: string){
  return m?.length;
}
//如果m不存在則短路直接返回undefined

剩餘引數

function func(...args: number[]){}

詳解Typescript裡的This - 知乎 (zhihu.com)

函式過載

function sum(m: number, n: number): number;
function sum(m: string, n: string): string;
function sum(m: any, n: any): any{
	//code block
}

04-TypeScript型別縮小

將不確定的型別進行型別範圍縮小。

typeof

function func(m: number|string){
	if(typeof m === "number") {}
	else {} //number
}

平等縮小

//switch
function func(m: "a"|"b"){
	switch (m) {
		case 'a': break;
		case 'b': break;
	}
}
//===...
function func(m: "a"|"b"){
	if(m === "a") {}
	//...
}

instanceof

function func(m: Data:string){
	if(m instanceof Data) {}
}

in

type Fish = {swim: () => void}
type dog = {run: () => void}

function func(animal: Fish|dog){
	if("swim" in animal) {} //Fish
}

05-TypeScript類

繼承:extends

class Parent{
	constructor(){}
}
class Child extends Parent{
	constructor(){
		super();
	}
}

修飾符

public、protected、private、static

readonly

class Parent{
	readonly xxx;
	//xxx只能在 構造器 或 欄位定義時 賦值
	constructor(){}
}

存取器

class Parent{
	set name(name){}
	get name(){}
}

抽象類abstract

...略...

06-TypeScript介面

//物件型別
interface Obj{
	name: string,
	age?: number,
	readonly sex: boolean
}
//索引型別
interface Index{
	[index: number]: string
}
//函式型別
interface Func{
	(n: number, m: number): number
}

繼承

介面支援多繼承,類只能單一繼承。

多型(面向介面程式設計)

...略...

Freshness

Freshness | 深入理解 TypeScript (jkchao.github.io)

interface IPerson{
  name: string
}
const p: IPerson = {
  name: "a",
  aname: "a"
} //報錯
//在p的賦值過程中,TypeScript對 物件字面量 進行嚴格檢查

泛型

function foo<T>(arg: T): T {}
// 顯式型別定義
foo<string>("abc")
// 隱式型別推導
foo("abc")

泛型約束

interface ILength{
	length: number
}
function getLength<T extends ILength>(args: T){
	return args.length;
}
getLength("aaa");
getLength([1, 2]);
getLength({length: 10});

07-TypeScript模組化開發

模組化

利用ES Module或CommonJS使檔案成為一個獨立的模組。

// ~/a.ts
const a = 1;
const b = 1;
// ~/b.ts
const a = 1;
const b = 1;
// ↑報錯,衝突
-------------
// ~/a.ts
const a = 1;
const b = 1;
// ~/b.ts
const a = 1;
export const b = 1;
// ↑ok

namespace名稱空間

namespace允許在模組內部進行更小粒度的作用域劃分。

型別查詢規則

.d.ts檔案

進行型別宣告(declare),用來做型別檢測。

內建型別宣告

內建JavaScript執行時的一些標準化API的宣告檔案。

TypeScript/lib at main · microsoft/TypeScript (github.com)

外部定義型別宣告

第三方庫的型別宣告,有時安裝第三方庫時沒有內建型別宣告,需要自行下載或配置。

DefinitelyTyped/DefinitelyTyped: The repository for high quality TypeScript type definitions. (github.com)

TypeScript: Search for typed packages (typescriptlang.org)

自定義型別宣告

//變數
let name = "name"; //.ts
declare let name: string; //.d.ts
//函式
function foo(){}; //.ts
declare function foo(): void; //.d.ts
//類
class xxx{}; //.ts
declare class xxx{}; //.d.ts
//模組
export defualt xxx; //.ts
declare module "xxx" {}; //.d.ts
//名稱空間
declare namespace ${
    function ajax(): void
}//.d.ts
$.ajax()//.ts

tsconfig.json

TypeScript: TSConfig Reference - Docs on every TSConfig option (typescriptlang.org)