TS學習筆記

来源:https://www.cnblogs.com/bbigger004/archive/2022/08/30/16638770.html
-Advertisement-
Play Games

類型 |類型 | 例子| 描述 | | | | | | number | 1,2,-2 | 任意數字 | | string | 'hi',"hi" | 任意字元串 | | boolean | true,false | 布爾值或者true false | | 字面量 | 其本身 | 限制變數的值就是該 ...


類型

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

介面interface與類型別名type

區別:

介面,只能為對象指定類型

類型別名,不僅可以給對象指定類型,實際上可以為任意類型指定別名

//介面
interface  IPerson = {
  name: string
  age: number
  sayHi(): void
}

// 類型別名
type IPerson = {
  name: string
  age: number
  sayHi(): void
}

let person: IPerson = {
  name: '劉老師',
  age: 18,
  sayHi() {}
}

//類型別名
  type NumStr = number | string
	
let numStr: NumStr = 33
let numStr2: NumStr = '66'

字面量類型

思考以下代碼,兩個變數的類型分別是什麼?

let str1 ='Hello Ts'
const str2 : 'Hello Ts'

通過 TS 類型推論機制,可以得到答案:

\1. 變數 str1 的類型為:string。

\2. 變數 str2 的類型為:'Hello TS'。

解釋:

\1. str1 是一個變數(let),它的值可以是任意字元串,所以類型為:string。

\2. str2 是一個常量(const),它的值不能變化只能是 'Hello TS',所以,它的類型為:'Hello TS'。

註意:此處的 'Hello TS',就是一個字面量類型。也就是說某個特定的字元串也可以作為 TS 中的類型。

除字元串外,任意的 JS 字面量(比如,對象、數字等)都可以作為類型使用。

let str1 = 'Hello TS'

const str2: 'Hello TS' = 'Hello TS'

let age: 18 = 18

使用模式:字面量類型配合聯合類型一起使用。
使用場景:用來表示一組明確的可選值列表。
比如,在貪吃蛇游戲中,游戲的方向的可選值只能是上、下、左、右中的任意一個。
解釋:參數 direction 的值只能是 up/down/left/right 中的任意一個。
優勢:相比於 string 類型,使用字面量類型更加精確、嚴謹


function changeDirection(direction: 'up' | 'down' | 'left' | 'right') {}

changeDirection('left')

枚舉類型

//枚舉
/**
 *enum
 */
enum Gender {
  Male = 0,//可以寫=0  也可以不寫
  Female = 1,
}

let i1: { name: string; gender: Gender };
i1 = {
  name: "孫悟空",
  gender: Gender.Male,
};
console.log(i1.gender === Gender.Female);
// 枚舉:

enum Direction {
  Up,
  Down,
  Left,
  Right
}

function changeDirection(direction: Direction) {}

changeDirection(Direction.Left)

枚舉的功能類似於字面量類型+聯合類型組合的功能,也可以表示一組明確的可選值。

枚舉:定義一組命名常量。它描述一個值,該值可以是這些命名常量中的一個。

解釋:

\1. 使用 enum 關鍵字定義枚舉。

\2. 約定枚舉名稱、枚舉中的值以大寫字母開頭。

\3. 枚舉中的多個值之間通過 ,(逗號)分隔。

\4. 定義好枚舉後,直接使用枚舉名稱作為類型註解。

可以直接使用 . 來訪問枚舉中的成員

數字枚舉 字元串枚舉

枚舉是 TS 為數不多的非 JavaScript 類型級擴展(不僅僅是類型)的特性之一。

因為:其他類型僅僅被當做類型,而枚舉不僅用作類型,還提供值 (枚舉成員都是有值的)。

也就是說,其他的類型會在編譯為 JS 代碼時自動移除。但是,枚舉類型會被編譯為 JS 代碼

enum Direction {
  Up = 'UP',
  Down = 'DOWN',
  Left = 'LEFT',
  Right = 'RIGHT'
}

​ ⬇

var Direction;
(function (Direction) {
    Direction["Up"] = "UP";
    Direction["Down"] = "DOWN";
    Direction["Left"] = "LEFT";
    Direction["Right"] = "RIGHT";
})(Direction || (Direction = {}));

說明:枚舉與前面講到的字面量類型+聯合類型組合的功能類似,都用來表示一組明確的可選值列表。

一般情況下,推薦使用字面量類型+聯合類型組合的方式,因為相比枚舉,這種方式更加直觀、簡潔、高效。

any類型

原則上不推薦使用any類型這會讓 TypeScript 變為 “AnyScript”(失去 TS 類型保護的優勢)。

因為當值的類型為 any 時,可以對該值進行任意操作,並且不會有代碼提示

let obj: any = { x: 0 }

// 訪問不存在的屬性 或者 賦值
// obj.aaa
// obj.aaa = 10

// 當作函數調用
// obj()

// 賦值給其他類型的變數
// let n: number = obj

// --

// let a
// a = 1
// a = ''
// a()

// function add(num1, num2) {}
// add(1, 2)
// add(1, '2')
// add(1, false)

解釋:以上操作都不會有任何類型錯誤提示,即使可能存在錯誤!

儘可能的避免使用 any 類型,除非臨時使用 any 來“避免”書寫很長、很複雜的類型!

其他隱式具有 any 類型的情況:1 聲明變數不提供類型也不提供預設值 2 函數參數不加類型。

註意:因為不推薦使用 any,所以,這兩種情況下都應該提供類型!

unknown與any

unknown只霍霍自己 賦值給別人是不行的 而any只要跟他沾邊都會被霍霍都變成any

unknown就是個類型安全的any 賦值給別人前必須做判斷

let e: unknown = 'str';
let s: string;
//unknown 賦值給別人需要先判斷類型
if (typeof e === "string") {
  s = e;
}
//或者類型斷言
s = e as string;
s = <string>e;


聯合類型

let a = "male" | "female"
a = "male";
a = "female";

typeof

void never

主要用於函數返回值的確定

function fn(num): void {
  if (num>0) {
    return; //不應有返回值
  } else {
    return undefined;
  }
}
function fn2(): never{
  throw new Error("出錯了");//就是執行不完 一定會出錯
}


object 與函數結構的類型聲明

一般是不用object 限制太寬泛了

let a1: object;
a1 = {}
a1 = function () {
  
};
//用於指定哪些屬性
let b1: { name: string, age?: number }//加上問好表示屬性可選
b1 = { name: '孫悟空' }
let c1: { name: string, [propName: string]: any }// [propName: string]: any表示可以有任意類型的屬性
c1 = { name: "豬八戒", age: 18, gender: "male" }
//定義函數的參數結構 的類型聲明
let d1: (a: number, b: number) => number;
d1 = function (a: number, b: number) { return a + b; };

array

//數組
let e1: string[];//表示字元串數組
e = ['a', 'b', 'c', 'd'];
let f1: number[];
let g1: Array<number>;

元組

長度固定的數組

//元組
/**
 * 語法: [類型,類型,類型]
 */
let h1: [string, string, number];
h1 = ["hello", "world", 123];

或 | 和 與&


// |  表示或   & 表示且

let j1: { name: string } & { age: number }
j1={name: "孫悟空",age:18}

編譯選項

tsc app.ts -w

-w watch模式 只監視app.ts

使用tsc 編譯此項目下的全部ts文件 前提是得由tsconfig.json文件 即使這個文件為空json也會按照預設的選項來編譯!

webpack打包TS

package.json 需要哪些包

{
  "name": "ts-webpack",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack",
    "start": "webpack  serve --open  "
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.18.13",
    "@babel/preset-env": "^7.18.10",
    "babel-loader": "^8.2.5",
    "clean-webpack-plugin": "^4.0.0",
    "core-js": "^3.24.1",
    "html-webpack-plugin": "^5.5.0",
    "ts-loader": "^9.3.1",
    "typescript": "^4.7.4",
    "webpack": "^5.74.0",
    "webpack-cli": "^4.10.0",
    "webpack-dev-server": "^4.10.0"
  }
}

webpack.config.js 定義打包的方式

//引入路徑包
const path = require("path");
//引入一個插件包
const HTMLWebpackPlugin = require("html-webpack-plugin");

//引入clean插件
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
module.exports = {
  //添加模式
  mode: "development",
  //指定入口文件
  entry: "./src/index.ts",
  //指定打包文件所在目錄
  output: {
    //指定目錄
    path: path.resolve(__dirname, "dist"),
    //指定名字
    filename: "index.js",
    //配置環境相容問題
    environment: {
      arrowFunction:false
    }
  },
  //指定打包時要用到的模塊
  module: {
    rules: [
      {
        //test指定的是規則生效的文件
        test: /\.ts$/, //匹配以ts結尾的文件
        //use 要使用的loader  數組中的內容從後往前執行
        use: [
          {
            //設置載入器
            loader: "babel-loader",
            //設置babel
            options: {
              //設置預定義的環境
              presets: [
                [
                  //指定環境的插件
                  "@babel/preset-env",
                  //配置信息
                  {
                    //要相容的預設瀏覽器
                    targets: {
                      //瀏覽器版本
                      "chrome": "58",
                      "ie":"11"
                    },
                    //指定corejs的版本
                    "corejs": "3",
                    //使用corejs的方式
                    "useBuiltIns": "usage"
                  }
                ]
              ] 
            },
          },
          "ts-loader",
        ],
        //exclude 排除哪些文件
        exclude: /node-modules/,
      },
    ],
  },
  //配置webpack的插件
  plugins: [
    new CleanWebpackPlugin(),
    new HTMLWebpackPlugin({
      // title: "這是一個自定義的title",
      template: "./src/index.html",
    }),
  ],
  //用來設置引用模塊
  resolve: {
    extensions: [".ts", ".js"],
  },
};

tsconfig.json ts的編譯方式

{
  "compilerOptions": {
    "module": "ES2015",
    "target": "ES2015",
    "strict": true
  }
}

//使用class關鍵字來定義一個類
/**
 *   屬性  
 *   方法
 */
class Person{
  //實例屬性
  name: string = "孫悟空";
  //在屬性前加關鍵字static可以定義類屬性(靜態屬性)即不需要創建實例就可訪問的屬性
  static age: number = 18;
  //只讀屬性
  readonly gender: string = "male";

  //實例方法
  say() {
    console.log('hello')
  }
  //靜態方法
  static run() {
    console.log('run')
  }

}
const per = new Person();
console.log('per.name', per.name);
console.log('per', per);
per.say();  
console.log('Person.age', Person.age)
Person.run();

構造函數與this

class Dog{
  name: string;
  age: number;
  //構造函數
  constructor(name: string, age: number) {
    console.log('構造函數執行了',this)
    this.name= name
    this.age= age
  }

  bark() {
    console.log('wangwangwang')
  }
}
const dog = new Dog('xiaohei',4);
console.log('dog',dog)

類的繼承

(() => {
  class Animal {
    name: string;
    age: number;
    constructor(name: string, age: number) {
      this.name = name;
      this.age = age;
    }
    sayHello() {
      console.log(`${this.name}sayHello`);
    }
  }

  class Dog extends Animal {
    sayHello(): void {
      console.log("wangwangwang"); //子類覆蓋掉父類的方法的形式叫重寫
    }
  }

  class Cat extends Animal {
    run() {
      console.log(`${this.name}run`);
    }
  }
  const dog = new Dog("旺財", 5);
  const cat = new Cat("咪咪", 3);
  console.log("cat", cat);
  console.log("dog", dog);
  dog.sayHello();
  cat.sayHello();
  cat.run();
})();

super

(() => {
  class Animal {
    name: string;

    constructor(name: string) {
      this.name = name;
  
    }
    sayHello() {
      console.log(`${this.name}sayHello`);
    }
  }

  class Dog extends Animal {
    age: number;
    constructor(name: string, age: number) { 
      super(name);//必須先調用父類的構造函數
      age = this.age;
    }

    sayHello(): void {
      super.sayHello(); //super表示當前類的父類
    }
  }

  const dog = new Dog('旺財',1);
  dog.sayHello();
})();

抽象類

(() => {
  abstract class Animal {
    //我們不希望直接用Animal來創建實例,我們只需要讓它是一個超類 用來被繼承
    //所以我們給它加上abstract   那麼這個類就只能被繼承    不能用它創建實例
    //抽象類可以添加抽象方法
    name: string;

    constructor(name: string) {
      this.name = name;
    }
    //抽象方法只能在抽象類里定義  抽象方法沒有方法體
    //子類必須對抽象方法進行重寫
    abstract sayHello(): void;
  }

  class Dog extends Animal {
    //非抽象類繼承抽象類 必須重寫父類中的抽象方法
    sayHello(): void {
      console.log("汪汪汪");
    }
  }

  const dog = new Dog("旺財");
  dog.sayHello();
})();

介面

(() => {
  /**
   * 對於類型聲明(類型別名) 只能聲明一次
   *
   * 對於介面 可以重覆聲明  多次聲明那麼創建的實例應把介面中的定義的都實現
   *           介面可以限制類的結構
   *           介面只定義類的結構不定義類的實際值
   *           介面的所有方法都是抽象方法
   *
   *
   *
   */
  //描述一個對象的類型   類型別名
  type myType = {
    name: string;
    age: number;
  };
  let obj: myType = {
    name: "sss",
    age: 1,
  };

  /**
   * 介面用來定義一個對象的結構
   * 用來定義一個類中應該包含哪些屬性和方法
   */
  interface myInterface {
    name: string;
    age: number;
  }
  interface myInterface {
    gender: string;
    sayHello(): void;
  }

  let obj1: myInterface = {//當作類型使用
    name: "aaa",
    age: 2,
    gender: "male",
    sayHello() {
      console.log("hello");
    },
  };

  //實現介面
  class Myclass implements myInterface { 
    name = '孫悟空';
    age = 18;
    gender = 'male';
    sayHello() { 
      console.log("嘿嘿")
    }
  }
})();

屬性的封裝

private getter setter

(() => {
  class Person {
    name: string;
    age: number;
    constructor(name: string, age: number) {
      this.name = name;
      this.age = age;
    }
  }

  let per = new Person("孫悟空", 18);
  console.log("per", per);
  per.name = "豬八戒";
  per.age = -18;
  console.log("per", per); //可以任意修改 年齡能有負數嘛?
  /**
   * 上面的屬性是在對象中設置的,屬性可以任意的被修改
   *  屬性可以任意被修改將會導致對象中的數據會變得非常不安全
   */
  class Animal {
    /**q
     * 可以在屬性前添加修飾符
     */
    public name: string; //公共屬性可以在任意位置(訪問)更改  預設就是public
    private age: number; //私有屬性 只能在類內部(訪問)修改
    constructor(name: string, age: number) {
      this.name = name;
      this.age = age;
    }
    //getter 添加方法讓私有屬性可以在外部訪問
    getAge() {
      return this.age;
    }
    //setter 設置屬性
    setAge(value: number) {
      if (value > 0) {
        this.age = value;
      }
    }
  }
  let dog = new Animal("旺財", 2);
  console.log("dog", dog);
  console.log("dog.getAge()", dog.getAge());
  dog.setAge(-8);
  console.log("dog", dog); //改不了
})();

protected 與 constructor 語法糖

(() => {
  class Person {
    name: string;
    age: number;
    constructor(name: string, age: number) {
      this.name = name;
      this.age = age;
    }
  }

  let per = new Person("孫悟空", 18);
  console.log("per", per);
  per.name = "豬八戒";
  per.age = -18;
  console.log("per", per); //可以任意修改 年齡能有負數嘛?
  /**
   * 上面的屬性是在對象中設置的,屬性可以任意的被修改
   *  屬性可以任意被修改將會導致對象中的數據會變得非常不安全
   */
  class Animal {
    /**q
     * 可以在屬性前添加修飾符
     */
    public _name: string; //公共屬性可以在任意位置 包括子類 (訪問)更改  預設就是public
    private _age: number; //私有屬性 只能在類內部(訪問)修改
    //protected   受保護的屬性,只能在當前類和當前類的子類中訪問
    constructor(name: string, age: number) {
      this._name = name;
      this._age = age;
    }
    // //getter 添加方法讓私有屬性可以在外部訪問
    // getAge() {
    //   return this.age;
    // }
    // //setter 設置屬性
    // setAge(value: number) {
    //   if (value > 0) {
    //     this.age = value;
    //   }
    // }

    //ts中設置獲取屬性 設置屬性 的方法  不會改變訪問數據的方法
    /**
     * 不是特別複雜的修改時  一般用不到
     */
    get age() {
      return this._age;
    }
    set age(value: number) {
      if (value > 0) {
        this._age = value;
      }
    }
  }
  let dog = new Animal("旺財", 2);
  // console.log("dog", dog);
  // console.log("dog.getAge()", dog.getAge());
  // dog.setAge(-8);
  console.log("dog.age", dog.age);
  // console.log("dog", dog); //改不了
  dog.age = 8;
  console.log("dog", dog);

  /**
   * 語法糖
   */

  class C {
    //得用public
    constructor(public name: string, public age: number) {}
  }
  let c = new C("666", 6);
  console.log("c", c);
})();

泛型

(() => {
  function fn(a: any): any {
    return a;
  }
  /**
   * 在定義函數或是類時遇到類型不明確的  可以使用泛型
   *
   */
  function fn1<T>(a: T): T {
    //我不知道a到底是是麽類型但是我知道 返回值和入參的類型時相同的
    return a;
  }
  fn1(10); //自動推斷
  fn1<string>("test"); //類型斷言

  function fn2<T, K>(a: T, b: K): T {
    console.log("b", b);
    return a;
  }
  fn2(123, "test");
  fn2<number, string>(333, "test");

  interface Test {
    length: number;
  }
  //泛型T得是Test的實現類(子類)
  function fn3<T extends Test>(a: T): number {
    return a.length;
  }
  fn3([1, 2, 2]); //傳入的參數的類型得是Test介面的實現類
})();

倉庫地址:https://gitee.com/bbigger004/tslearn.git


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 8 JSON 因平時工作時,使用JSON的場景比較多,其JSON語法不再介紹,僅介紹在JavaScript中JSON的解析和序列化。 8.1 JSON 對象 JSON對象有兩個方法: stringify():將JavaScript序列化為JSON字元串 parse():將JSON解析為原生JavaS ...
  • 在B/S系統開發中,前後端分離開發設計已成為一種標準,而VUE作為前端三大主流框架之一,越來越受到大家的青睞,Antdv是Antd在Vue中的實現。本系列文章主要通過Antdv和Asp.net WebApi開發學生信息管理系統,簡述前後端分離開發的主要相關內容,僅供學習分享使用,如有不足之處,還請指... ...
  • 閑聊: 小穎今年四月底從西安跑到深圳來找工作,本來想著好好賺錢還房貸,結果快轉正了被通知要麼無薪待崗,要麼辦理離職,嗯~ o(* ̄▽ ̄*)o.............................. 想罵人咋辦 ? 小穎之前沒怎麼寫過小程式,到這邊後接手了離職小姐姐的工作,看代碼、看api、自己試 ...
  • 這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 File() File() 構造器創建新的 File 對象實例。 語法 var myFile = new File(bits, name[, options]); 參數 bits 一個包含ArrayBuffer,ArrayBufferVi ...
  • 原文鏈接:https://dev.to/ruppysuppy/7-tips-for-clean-react-typescript-code-you-must-know-2da2 “乾凈的代碼”不僅是可以正常運行的代碼。它指的是組織整齊、易於閱讀、易於理解且易於維護的代碼。 讓我們來看看 React ...
  • 進入/離開 & 列表過渡 點擊打開視頻講解更加詳細 概述 Vue 在插入、更新或者移除 DOM 時,提供多種不同方式的應用過渡效果。包括以下工具: 在 CSS 過渡和動畫中自動應用 class 可以配合使用第三方 CSS 動畫庫,如 Animate.css 在過渡鉤子函數中使用 JavaScript ...
  • 本文是深入淺出 ahooks 源碼系列文章的第十五篇,該系列已整理成文檔-地址。覺得還不錯,給個 star 支持一下哈,Thanks。 本篇接著針對關於 DOM 的各個 Hook 封裝進行解讀。 useFullscreen 管理 DOM 全屏的 Hook。 該 hook 主要是依賴 screenfu ...
  • Windows的靈魂是什麼?當然是Window,當方便快捷的多視窗進入人們視野的時候,大家無不為之驚呼太好用了!! ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...