1.TS基本類型

一、TS類型聲明

1.在.ts文件中定義變量a,提示無法重新聲明塊范圍變量“a”。

原因分析:TS誤以為這些文件將在未來的某個時間合并,所以拋出了變量“重復”的錯誤。
解決方法:在文件末尾加上export {}即可。(項目中已經有了exports模塊化工具后才能使用)

let a: number = 12;
export {}
2.如果變量的聲明和賦值是同時進行的,TS可以對變量進行 \color{red}{自動類型檢測。}
let b = 13; // 聲明變量b 并賦值為13
b = true; // 報錯,因為b的類型是number,不能賦值為boolean
3.如果只聲明變量不賦值,且沒有指定變量的類型,TS會自動判斷該變量的類型為 \color{red}{any,(隱式的any)}
// 變量只聲明不賦值,且沒有指定變量的類型時,TS自動推斷變量的類型為any
let c;
c = 1;
c = "hello";
c = true;
4.給函數(shù)的 \color{red}{參數(shù)}\color{red}{返回值} 聲明類型
function sum(a: number, b: number):number {
  return a + b;
}

二、TS基本類型

類型 例子 描述
number 1,2,3 任意數(shù)字
string 'hello' 任意字符串
boolean true,false 布爾值true或false
字面量 其本身 限制變量的值就是該字面量的值
any * 任意類型
unknown * 類型安全的any
void 空值(undefined) 沒有值(或undefined)
never 沒有值 不能是任何值
object {name:'孫悟空'} 任意的JS對象
array [1,2,3] 任意JS數(shù)組
tuple [4,5] 元組,TS新增類型,固定長度的數(shù)組
enum enum{A,B} 枚舉,TS新增類型
1.字面量類型

字面量類型的變量,只能被賦值為指定的值。

// 字面量類型的變量,只能被賦值為指定的值
let d: "male" | "female";
d = "male";
d = "female";
TS類型聲明時, \color{red}{|} 代表 \color{red}{或}。
// 聲明變量類型時,可以用 | 連接多個類型,表示該變量可以是多個類型中的一個
let e: string | number;
e = "hello";
e = 123;
2.any和unknown的區(qū)別。

(1)可以把任意類型的值賦值給any或unknown類型的變量。

// any表示任意類型
let c: any;
c = 1;
c = "hello";
c = true;
// unknown 表示未知類型的值
let f: unknown;
f = 10;
f = "hello";
f = true;

(2)any類型的變量可以直接賦值給其他任意類型的變量;unknown類型的變量則不能直接賦值給其他類型的變量,除非對unknown類型的變量做 \color{red}{類型判斷}\color{red}{類型斷言}。

類型斷言語法格式:\color{red}{變量 as 類型} 或者 \color{red}{<類型>變量}

let g: string;
g = c; // 不報錯,因為c的類型是any
g = f; // 報錯,不能將類型“unknown”分配給類型“string”

g = f as string; // 類型斷言,告訴編譯器f是string類型
g = <string>f; // 類型斷言,告訴編譯器f是string類型
// 類型判斷
if (typeof f === "string") {
  g = f;
}
3.void類型

void表示沒有任何類型,一般用于 函數(shù)沒有返回值 或者 返回undefined。

// void 表示沒有任何類型,一般用于函數(shù)沒有返回值或者返回undefined
function sum(x: number, y: number): void {
  // return undefined;
 }

沒有聲明函數(shù)返回值的類型且函數(shù)沒有返回值時,函數(shù)返回值的類型默認為隱式的void。

4.never類型

never表示不能是任何值,永遠不會有返回結果。例如函數(shù)內拋出錯誤。

function sum2(): never { 
  throw new Error("報錯了!")
}
5.object類型

{屬性名:類型,屬性名?:類型,[任意名稱:類型]:類型}

  • 不加 \color{red}{?} 表示屬性是必須的
  • \color{red}{?} 表示屬性是可選的
  • [propName: string]:any 表示該對象中可以添加任意個屬性,屬性名是string類型,屬性值是any類型
// object 表示一個js對象,但這種寫法不太常用
let h: object;
h = {};
/*
  常用的寫法:{屬性名:類型,屬性名?:類型,[任意名稱:類型]:類型}。
  ? 表示屬性是可選的;不加?表示屬性是必須的
  [propName: string]:any 表示該對象中可以添加任意個屬性,屬性名是string類型,屬性值是any類型
*/ 
let i: { x: number, y?: string, [propName: string]: any };
i = { x: 1, y: "hello", name: "張三", age: 18 }; // x是必須有的,y可有可無,name和age也是可有可無
// Function 表示一個函數(shù),但這種寫法不太常用
let j: Function;
j = function () { };
// 常用的寫法:(參數(shù)名:類型) => 返回值類型
let k: (a: number, b: string) => number;
k = function (a, b):number { return a + b.length; };
6.array類型

\color{red}{類型[ ]} 或者 \color{red}{Array<類型>}

/*
 * 數(shù)組類型的聲明:類型[] 或 Array<類型>
*/ 
let l: number[]; // 數(shù)組中的元素是number類型
l = [1, 2, 3];

let m: Array<string>; // 數(shù)組中的元素是string類型
m = ["a", "b", "c"];
7.tuple類型

元組就是固定長度的數(shù)組。

// 元組就是固定長度的數(shù)組
let n: [string, number]; // 元組類型,表示一個元組中只能有兩個元素,第一個元素是string類型,第二個元素是number類型
n = ["hello", 123];
8.enum類型

\color{red}{enum 自定義枚舉名稱\{枚舉值1,枚舉值2\}} 或者 \color{red}{enum 自定義枚舉名稱\{枚舉值1 = 1,枚舉值2 = 2\} }

// 枚舉類型
enum Gender { Male, Female }; // 定義枚舉類型Gender,表示性別,有男和女兩種
let o = {name: "張三", gender: Gender.Male}; // 定義對象o,name是字符串,gender是Gender枚舉類型
console.log(o.gender === Gender.Male); // true
9.類型的別名

type 類型別名 = 類型

// 類型的別名: type 類型別名 = 類型
type myType = number[]; // myType等價于number類型的數(shù)組
let z: myType = [1, 2, 3]; // z的數(shù)據(jù)類型是myType,一個number類型的數(shù)組

三、接口

1.定義類結構

(1)用interface 關鍵字來定義接口;用 implements 關鍵字來實現(xiàn)接口。
(2)接口可以用來定義 類的結構,即一個類中應該有哪些屬性和方法。
(3)接口中的 屬性方法 都是 抽象的(即不能有實際的值),抽象的屬性和方法必須被實現(xiàn)(重寫)。

// interface關鍵字來定義接口
interface myInterface {
  name: string;
  sayHello(): void;
}

// implements關鍵字來實現(xiàn)接口
class MyClass implements myInterface {
  name: string;
  constructor(name: string) {
    this.name = name; // 實現(xiàn)抽象屬性
  }
  // 實現(xiàn)抽象方法
  sayHello(): void {
    console.log("你好!");
   }
 }
2.類型聲明

(1)接口也可以當做類型聲明來使用。
(2)不同的是,接口可以 重復聲明,而類型聲明不可以。

// A和B是等價的
interface A {
  name: string;
}
interface A {
  age: number;
}
type B = {
  name: string;
  age: number;
}

四、泛型

1. 什么是泛型

(1)在定義 函數(shù)接口 時,不預先指定具體的類型,而在 使用時 再指定類型的一種特性。
(2)使用 any 會跳過類型檢查,且會丟失參數(shù)和返回值之間的類型約束關系。

2. 泛型函數(shù)

(1)重點在于用 function 關鍵字 定義函數(shù) 時,怎么使用泛型。
(2)基礎用法

// 泛型函數(shù),T和K是類型變量,可以用任意字母表示
function fn<T,K>(a: T, b: K): T {
  console.log(b);
  return a;
}
fn<number,string>(10, "hello"); // 指定T是number類型,K是string類型
fn(10, "hello");                // 不指定類型,TS自動推斷T是number類型,K是string類型

(3)實際用法——用function關鍵字聲明函數(shù)組件

① 用 function 定義了一個函數(shù)組件,用到了泛型T,并用extends關鍵字對T進行了 泛型約束。
② 入參的類型是 泛型接口 類型,名為 TableProps<T>。
③ 返回值是 JSX.Element類型。

import React from 'react';

// 泛型接口定義組件 Props
interface TableProps<T> {
  data: T[];
  columns: Array<{
    key: keyof T;
    title: string;
    render?: (value: T[keyof T], record: T) => React.ReactNode;
  }>;
}

// 泛型函數(shù)組件
function GenericTable<T extends { id: string }>({
  data,
  columns
}: TableProps<T>): JSX.Element {
  return <div></div>
}
3. 泛型接口

(1)本質就是 接口,而這個接口中用到了 泛型,目的是指定 變量 的類型。
(2) 基礎用法

// 泛型接口
interface ApiResponse<T> {
    code: number;
    message: string;
    data: T;  // data 的類型由使用接口時指定
}
// 用戶信息的接口響應數(shù)據(jù)
let userResponse: ApiResponse<{ name: string; age: number }> = {
    code: 200,
    message: "Success",
    data: { name: "Alice", age: 30 } // data 必須是 { name: string; age: number }
};

(2) 實際用法——用箭頭函數(shù)聲明函數(shù)組件

① 這里用 箭頭函數(shù) 定義了一個 函數(shù)組件,并用 變量 進行存接收存儲。
React.FC<UserProps>:這是對組件整體的類型注解,而組件存儲到了變量中,所以實際修飾的是 \color{red}{變量},變量的類型就是 \color{red}{泛型接口}。
React.FC 是 React已經定義好的 內置泛型接口, 表示 變量的類型React 函數(shù)組件。
<UserProps> 是泛型參數(shù),React.FC這個泛型變量接受到泛型參數(shù)后,在內部用它指定了組件的 props 類型

// 1. 定義 Props 接口
interface UserProps {
  name: string;
  age: number;
  isActive?: boolean; // 可選屬性
}

// 2. 組件類型注解
const UserCard: React.FC<UserProps> = (props) => {
  // 此時 props 的類型已經被推斷為 UserProps
  // 包含 name: string, age: number, isActive?: boolean
  // 以及 React.FC 隱含的 children?: React.ReactNode
}
4. 泛型類
// 泛型類
class B<T> {
  name: T;
  constructor(name: T) {
    this.name = name;
  }
}
let b1 = new B<string>("張三"); // 指定T是string類型
5. 泛型約束

如果不希望泛型可以是任何類型,而是希望它 至少滿足某些條件。這時就需要使用 extends 關鍵字來實現(xiàn)泛型約束。

// 定義一個接口,表示必須有l(wèi)ength屬性
interface Lengthwise {
  length: number;
}
// 定義一個泛型函數(shù),T必須是Lengthwise類型或其子類型
function fn1<T extends Lengthwise>(a: T): number {
  return a.length; // 現(xiàn)在可以安全地訪問length屬性
}
6. 泛型默認值

...

五、常用的內置類型工具

1. Omit<T, K> 泛型工具類型

(1)用于從 類型T排除 指定的 屬性集合K,生成一個 新的類型。

type myNewType = Omit<T, K>

type myNewType= Omit<myOldType,"name" | "age">  // myNewType中包含myOldType中,除了name和age之外的所有類型。
2. Partial<T> 泛型工具類型

(1)Partial 將類型 T 的所有屬性都轉換為 可選屬性(即添加 ? 修飾符)。
(2)Partial 只會影響對象的 直接屬性,不會遞歸地將嵌套對象的屬性變?yōu)榭蛇x。

type myNewType = Partial<T>

/*
*  1.定義一個變量partialUser,變量類型是用 Partial修飾后的 myOldType類型。
*  2.變量 partialUser可以只包含 myOldType 類型的部分屬性。
*/ 
let partialUser: Partial<myOldType> = { name: '張三', age: 25 };
3. 常用類型工具

(1)Partial<T>:將類型 T 的所有屬性設置為可選的。
(2)Required<T>:將類型 T 的所有屬性設置為必需的。
(3)Readonly<T>:將類型 T 的所有屬性設置為只讀的。
(4)Record<K, T>:構造一個類型,其屬性名的類型為 K,屬性值的類型為 T。
(5)Pick<T, K>:從類型 T 中選取一組屬性 K 來構造類型。
(6)Omit<T, K>:從類型 T 中排除一組屬性 K 來構造類型。
(7)Exclude<T, U>:從類型 T 中排除那些可以賦值給 U 的類型。
(8)Extract<T, U>:從類型 T 中提取那些可以賦值給 U 的類型。
(9)NonNullable<T>:從 T 中排除 null 和 undefined。
(10)Parameters<T>:由函數(shù)類型 T 的參數(shù)類型組成的元組類型。
(11)ReturnType<T>:函數(shù)類型 T 的返回值類型。
(12)InstanceType<T>:構造函數(shù)類型 T 的實例類型。
(13)ThisParameterType<T>:提取函數(shù)類型 T 的 this 參數(shù)類型,如果沒有則返回 unknown。
(14)OmitThisParameter<T>:從函數(shù)類型 T 中移除 this 參數(shù)。
(15)ThisType<T>:用于標記上下文 this 類型的工具類型。

interface User {
  name: string;
  age: number;
  email?: string;
}

// (1)Partial: 所有屬性變?yōu)榭蛇x
type PartialUser = Partial<User>;
// 等價于 { name?: string; age?: number; email?: string; }

// (2)Required: 所有屬性變?yōu)楸剡x
type RequiredUser = Required<User>;
// 等價于 { name: string; age: number; email: string; }

// (3)Readonly: 所有屬性變?yōu)橹蛔x
type ReadonlyUser = Readonly<User>;
// 等價于 { readonly name: string; readonly age: number; readonly email?: string; }

// (4)Record: 構建一個類型,其鍵為字符串,值為User
type UserRecord = Record<string, User>;

// (5)Pick: 選取User中的'name'和'age'
type UserNameAge = Pick<User, 'name' | 'age'>;
// 等價于 { name: string; age: number; }

// (6)Omit: 排除User中的'age'
type UserWithoutAge = Omit<User, 'age'>;
// 等價于 { name: string; email?: string; }

// (7)Exclude: 從聯(lián)合類型中排除某些類型
type T0 = Exclude<"a" | "b" | "c", "a">; // "b" | "c"

// (8)Extract: 從聯(lián)合類型中提取某些類型
type T1 = Extract<"a" | "b" | "c", "a" | "f">; // "a"

// (9)NonNullable: 排除null和undefined
type T2 = NonNullable<string | number | null | undefined>; // string | number

// (10)Parameters: 獲取函數(shù)的參數(shù)類型
declare function f1(arg: { a: number; b: string }): void;
type T3 = Parameters<typeof f1>; // [{ a: number; b: string }]

// (11)ReturnType: 獲取函數(shù)的返回類型
type T4 = ReturnType<() => string>; // string

// (12)InstanceType: 獲取構造函數(shù)的實例類型
class C {
  x = 0;
  y = 0;
}
type T5 = InstanceType<typeof C>; // C

// (13)ThisParameterType: 獲取函數(shù)的this參數(shù)類型
function toHex(this: number) {
  return this.toString(16);
}
type T6 = ThisParameterType<typeof toHex>; // number

// (14)OmitThisParameter: 移除this參數(shù)
type T7 = OmitThisParameter<typeof toHex>; // () => string

// (15)ThisType: 用于標記對象中方法的this類型
interface MyObject {
  text: string;
  highlight: () => void;
}
type MyObjectThis = ThisType<{ enable: () => void }>;
// 通常與具體對象定義一起使用,例如在選項對象中指定this類型

六、Typescript基本使用

(1)安裝,npm install -g typescript。
(2)配置typescript.config.ts文件。(不配置也可以直接進行第三步)
(3)命令行里輸入 tsc 文件名.ts進行編譯;或者命令行輸入tsc -w,當前ts文件變更時會自動編譯到js文件。
(4)在項目里使用時,可以結合webpack或者vite等打包工具,進一步配置webpack或者vite。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容