柚子快報邀請碼778899分享:TypeScript學習筆記
柚子快報邀請碼778899分享:TypeScript學習筆記
TypeScript學習筆記
1、運行環(huán)境(webpack)
1.1、初始化
npm init -y
npm i -D webpack webpack-cli webpack-dev-server html-webpack-plugin typescript ts-loader
1.2、webpack.config.js
const path = require('path')
const htmlWebpackPlugin = require("html-webpack-plugin")
module.exports = {
// 指定文件入口
entry: path.resolve(__dirname, './src/index.ts'),
// 指定打包文件目錄
output: {
// 指定打包文件目錄
path: path.resolve(__dirname, './dist'),
// 指定打包文件名稱
filename: 'bundle.js',
},
// 開啟source-map,方便調試
devtool: "inline-source-map",
// require時可以省略對應的后綴名,如有同名文件,會依次匹配
resolve: {
extensions: [".ts", ".js"]
},
// 指定打包時要使用得模塊
module: {
// 指定打包規(guī)則
rules: [
{
// 目標文件
test: /\.ts$/,
//要使用的loader
use: {
loader: "ts-loader"
},
//要排除的文件夾
exclude: /node_modules/
}
]
},
plugins: [
// 自定義html打包插件
new htmlWebpackPlugin({
// 模板文件
template: "./src/index.html",
// 輸出文件
filename: "index.html",
})
],
// 本地開發(fā)服務器配置
devServer: {
// 文件路徑
static: './dist',
// 第一次構建是否自動用瀏覽器打開網(wǎng)頁
open: true,
// 端口
port: 9000
},
// 模式development|production
mode: 'development',
// 指定Webpack構建的環(huán)境為web
target: "web"
}
1.3、tsconfig.json
{
// 編譯選項
"compilerOptions": {
// 目標語言的版本
"target": "ES6",
// 生成代碼的模板標準
"module": "ES6",
// 開啟所有嚴格的類型檢查
"strict": true
}
}
1.4、index.ts
alert("hello world in typescript!")
1.5、index.html
Hello World!
1.6、package.json
{
"name": "typescript",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "webpack-dev-server --open",
"build": "webpack --mode production"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"html-webpack-plugin": "^5.5.3",
"ts-loader": "^9.4.4",
"typescript": "^5.1.6",
"webpack": "^5.88.1",
"webpack-cli": "^5.1.4",
"webpack-dev-server": "^4.15.1"
}
}
1.7、測試
2、數(shù)據(jù)類型
ts類型是在開發(fā)的時候檢測,編譯后不存在類型,ts具有類型推導能力,只有在無法推斷或需明確指定才需顯式聲明類型
any、unknowObjectNumber、String、Boolean(包裝類)number、string、boolean1、‘xumeng03’、true(字面量類型)never(不存在的值)
2.1、any
不進行類型檢測,使用如同Js里的變量
let str1: any = 'xumeng03'
let str2: string;
str2 = str1;
let str3: unknown;
str3 = str1;
2.2、unknow
不認為變量為任意一種類型
let str1: unknown = 'xumeng03'
let str2: string;
// 報錯
// str2 = str1;
let str3: any;
str3 = str1;
2.3、基礎類型
1、number
可以用來表示整數(shù)和分數(shù)
屬性描述MAX_VALUE最大值MIN_VALUE最小值POSITIVE_INFINITY正無窮大NEGATIVE_INFINITY負無窮大
方法示例描述toString()把數(shù)字轉換為字符串,使用本地數(shù)字格式順序valueOf()返回一個 Number 對象的原始數(shù)字值toPrecision()num.toPrecision(1)把數(shù)字格式化為指定的長度(小數(shù)點不算)toFixed()toFixed(1)把數(shù)字轉換為字符串,并指定位小數(shù)點位數(shù)
// 數(shù)字類型
let age: number = 22;
console.log("數(shù)字類型", age);
2、string
''和""可以表示常規(guī)字符串,``可以表示插值字符串
屬性描述length字符串的長度
方法描述charAt()指定位置的字符charCodeAt()指定的位置的字符的 Unicode 編碼concat()連接兩個或更多字符串,返回新的字符串indexOf()指定的字符串值在字符串中首次出現(xiàn)的位置lastIndexOf()指定的字符串值在字符串中反向第一次出現(xiàn)的位置localeCompare()用本地特定的順序來比較兩個字符串;大于0當前字符串大;等于0字符串一樣大;小于0當前字符串小match()查找找到一個或多個正則表達式的匹配replace()替換與正則表達式匹配的子串search()檢索與正則表達式相匹配的值split()把字符串分割為子字符串數(shù)組substr(start, length)從起始索引號提取字符串中指定數(shù)目的字符substring(start,stop)提取字符串中兩個指定的索引號之間的字符toLowerCase()轉小寫toUpperCase()轉大寫
// 字符串類型
// @ts-ignore
let name: string = "xumeng03";
console.log("字符串類型", name);
let introduce: string = `my name is ${name}, my age is ${age}`;
console.log("字符串類型", introduce);
3、boolean
值為true/false
// 布爾類型
let isStudent: boolean = false
console.log("布爾類型", "是否學生", isStudent);
2.4、包裝類型
1、Number
let a1: Number = Number(1)
let a2: number;
//錯誤
// a2 = a1;
a2 = a1.valueOf();
2、String
let a1: String = String('xumeng03')
let a2: string;
//錯誤
// a2 = a1;
a2 = a1.valueOf();
3、Boolean
let a1: Boolean = Boolean(true)
let a2: boolean;
//錯誤
// a2 = a1;
a2 = a1.valueOf();
2.5、引用類型
1、對象
Object:可以包含所有JS類型,一旦賦值無法進行屬性新增object:可以包含所有的引用類型(數(shù)組類型、對象類型、函數(shù)類型)、包裝類(Number、String、Boolean),不能包含原始類型{}:如同Object
2、接口
interface通常用于描述類、對象;
基礎用法
interface IPerson {
// 必選屬性
readonly id: number; // 只讀屬性
name: string;
age: number;
// 可選屬性
address?: string;
// 索引簽名
[key: string]: any;
}
let zhangsan: IPerson = {
id: 1,
name: "zhangsan",
age: 23,
// 可選屬性
address: '中國',
// 索引簽名
tag: [1, 2, 3]
}
// 錯誤,id是只讀屬性
// zhangsan.id = 2
接口繼承(可多繼承)
// 接口
interface IPerson {
// 必選屬性
id: number;
name: string;
age: number;
}
interface Chinese extends IPerson {
address: string;
}
let zhangsan: Chinese = {
id: 1,
name: "zhangsan",
age: 23,
// 可選屬性
address: '中國'
}
接口實現(xiàn)
// 接口
interface IPerson {
// 必選屬性
id: number;
name: string;
age: number;
}
class Person implements IPerson {
id: number;
name: string;
age: number;
constructor(id: number, name: string, age: number) {
this.id = id;
this.name = name;
this.age = age;
}
}
3、數(shù)組
方法描述concat()連接兩個或更多的數(shù)組,并返回結果every()檢測數(shù)值元素的每個元素是否都符合條件filter()檢測數(shù)值元素,并返回符合條件所有元素的數(shù)組forEach()數(shù)組每個元素都執(zhí)行一次回調函數(shù)indexOf()搜索數(shù)組中的元素,并返回它所在的位置;如果搜索不到,返回-1join()把數(shù)組的所有元素放入一個字符串lastIndexOf()返回一個指定的字符串值最后出現(xiàn)的位置map()通過指定函數(shù)處理數(shù)組的每個元素,并返回處理后的數(shù)組pop()刪除數(shù)組的最后一個元素并返回刪除的元素push()向數(shù)組的末尾添加一個或更多元素,并返回新的長度reduce()將數(shù)組元素計算為一個值(從左到右)reverse()反轉數(shù)組的元素順序返回一個字符串shift()刪除數(shù)組并返回數(shù)組的第一個元素unshift()向數(shù)組的開頭添加一個或更新元素,并返回新的長度slice(start, stop)選取數(shù)組的的一部分,并返回一個新數(shù)組some()檢測數(shù)組元素中是否有元素符合指定條件sort()對數(shù)組的元素進行排序splice(start, removeLength, addStr)從數(shù)組中添加或刪除元素toString()把數(shù)組轉換為字符串,并返回結果
// 數(shù)組類型
let hobby: string[] = ['book', 'code']
// let hobby: Array
console.log("數(shù)組類型", hobby);
let code: (string | number)[] = [1, 'java']
console.log("數(shù)組類型", code);
// 多維數(shù)組
let books: [string[], number[]] = [['book', 'code'], [1, 2]]
// IArguments
function a(...args: any[]) {
let a: IArguments = arguments
console.log(a)
}
a(1,2,2,3,3,3,3,3,3,3,2)
4、元組
// 元組類型
let userinfo: [string, number, boolean] = ['zhangsan', 23, false]
console.log("元組類型", userinfo);
5、函數(shù)
// 函數(shù)定義
let fun1 = function (a: string, b: string): string {
return a + b;
}
let fun2 = (a: string, b: string): string => {
return a + b;
}
// 可選參數(shù)
type Fun3 = (a: string, b: string, c?: string) => string
let fun3: Fun3 = (a, b, c): string => {
return a + b;
}
console.log(fun2('1', '2'));
console.log(fun3('1', '2', '3'));
// 默認值(不可與可選參數(shù)一起用)
type Fun4 = (a: string, b: string) => string
let fun4 = (a = 'abc', b: string = 'def'): string => {
return a + b;
}
console.log(fun4());
// 函數(shù)重載
function fun5(a: string): string;
function fun5(a: number): number;
function fun5(a: string | number): string | number {
return a;
}
6、枚舉
// 枚舉,推薦使用常量枚舉,不會額外生成對象
enum ROLE {
Student,
Teacher,
ADMIN
}
console.log("枚舉類型", ROLE.ADMIN, ROLE[0]);
const enum ROLE1 {
Student,
Teacher,
ADMIN
}
console.log("枚舉類型", ROLE1.ADMIN);
const enum ROLE2 {
Student = 1,
Teacher = 5,
ADMIN
}
console.log("枚舉類型", ROLE2.ADMIN);
const enum ROLE3 {
Student = 'a',
Teacher = 'b',
ADMIN = 'c'
}
console.log("枚舉類型", ROLE3.ADMIN);
console.log("枚舉類型", ROLE[0]);
// 數(shù)字枚舉可以反向映射,字符串枚舉不行
// console.log("枚舉類型", ROLE3['a']);
7、類
// 類
class Person {
// 實例屬性(修飾符public、protected、private)
name: string = 'xumeng';
age: number = 22;
// 實例私有屬性
private _id: number = 1
// 實例只讀屬性
readonly _type: string = '多細胞生物'
get getId() {
return this._id
}
set setId(id: number) {
this._id = id
}
// 靜態(tài)屬性
static type: string = '人類'
// 構造方法
constructor(name: string, age: number, world: (...args: any[]) => any) {
this.name = name
this.age = age
this.world = world
}
// 原型方法
hello() {
return "hello!"
}
// 實例方法
world: () => "";
}
// 實例
let person = new Person("xumeng03", 22, () => "world");
console.log(person, person.getId, Person.type, person.hello(), person.world());
// 繼承
class Chinese extends Person {
address: string = '中國';
constructor(name: string, age: number, address: string) {
super(name, age, () => "world")
this.address = address
}
hello() {
return "你好世界!"
}
}
let chinese = new Chinese("xumeng03", 22, '上海')
// 判斷對象是否是目標類的實例
console.log(chinese instanceof Person);
8、抽象類
// 抽象類
abstract class Animal {
// 實例屬性
abstract name: string;
// 實例方法
abstract eat: () => string;
// 原型方法
abstract speak(): string;
}
class Cat extends Animal {
name: string = 'cat';
constructor() {
super();
this.eat = () => ""
}
eat: () => "";
speak(): string {
return "miao~";
}
}
let cat = new Cat()
console.log(cat);
2.6、聯(lián)合類型&交叉類型
1、聯(lián)合類型
兩者滿足任意一個即可
let strOrNum: string | number='abc';
strOrNum = 1
2、交叉類型
需同時滿足兩者
class Person1 {
id: number
constructor(id: number) {
this.id = id
}
}
class Person2 {
name: string
constructor(name: string) {
this.name = name
}
}
let person: Person1 & Person2 = {
id: 1,
name: "xumeng03"
}
2.7、內置對象
let date: Date = new Date();
let reg: RegExp = new RegExp(/\w/);
let err: Error = new Error("Error");
let xhr: XMLHttpRequest = new XMLHttpRequest();
let html1: HTMLHtmlElement | null = document.querySelector('html')
let input1: HTMLInputElement | null = document.querySelector('input')
let div1: NodeList = document.querySelectorAll('div')
let div2: NodeListOf
let storage:Storage = localStorage
2.8、特殊類型
1、null、undefined
null表示對象值缺失,undefined表示初始化變量為一個未定義的值,嚴格模式(默認模式)不可混用
// null類型、undefined類型
let a: null = null
console.log("null類型", a);
let b: undefined = undefined
console.log("undefined類型", b);
2、void
常用于函數(shù)的返回值
// void類型
function hello(): void {
alert("hello world");
}
hello()
3、never
是所有類型(包括 null 和 undefined)的子類型,表示從不會出現(xiàn)的值/無終點
type A = 'code' | 'write'
// 新增屬性會導致TheType函數(shù)報錯,可以起到邏輯完整性檢測的作用
// type A = 'code' | 'write' | 'read'
function TheType(type: A) {
switch (type) {
case "code":
console.log("code");
break
case "write":
console.log("write");
break
default:
const theType: never = type
break
}
}
4、symbol
let a1: symbol = Symbol(1)
let a2: symbol = Symbol(1)
// Symbol.for會尋找有沒有當前key,如果有直接用
console.log(a1, a2, a1 === a2, Symbol.for('xumeng03') === Symbol.for('xumeng03'))
let a = {
id: 1,
[a1]: 1,
[a2]: 2,
}
// 獲取所有屬性值(string/symbol)
console.log(Reflect.ownKeys(a));
// 生成器(靈活的控制函數(shù)的暫停執(zhí)行)
function* progress() {
yield 33
yield 66
return 99.9
}
const generator = progress()
console.log(generator.next())
console.log(generator.next())
console.log(generator.next())
// 生成器(分段傳參)
function* progress1(num: number) {
let result = 0
console.log(num, result)
// 第一個next在此處卡住
result = yield num + result;
console.log(num, result)
// 第二個next在此處卡住,第三個next從此處繼續(xù)執(zhí)行
result = yield num + result;
console.log(num, result)
}
const generator1 = progress1(1)
console.log(generator1.next())
console.log(generator1.next(2))
console.log(generator1.next(3))
// 迭代器,可迭代對象(string、array、Set、NodeList、Arguments、Map)
// string
let str = 'xumeng03'
for( let text of str) {
console.log(text) //字符串每個遍歷打印
}
// 數(shù)組
const bears = ['book', 'code', 'game']
for( let bear of bears) {
console.log(bear)
}
2.8、類型斷言
function ilength(str: string | number) {
return (str as string).length;
}
console.log(ilength('abc'));
console.log(ilength(123));
let strOrNum: string | number;
console.log("類型斷言", (strOrNum! as string).includes("a"));
console.log("類型斷言", (
2.9、自定義類型
type通常用于描述函數(shù)簽名、聯(lián)合類型、工具類型、映射條件類型;
// 自定義類型
type Direction = 'up' | 'down'
let abc: Direction;
abc = 'up'
type s1 = string
type s2 = string | number
type s3 = () => string
2.10、內置工具類型
1、Record
type k = 1 | 2 | 3
interface Student {
name: string;
age: number;
}
const p: Record
1: {
name: 'xumeng01',
age: 20
},
2: {
name: 'xumeng02',
age: 20
},
3: {
name: 'xumeng03',
age: 20
},
}
2、Partial
讓傳入類型中的所有屬性變成都是可選的
interface Student {
name: string;
age: number;
}
// 報錯,name、age為必選屬性
// const student1: Student = {}
const student2: Partial
3、Required
讓傳入類型中的所有屬性變成都是必選的
interface Student {
name?: string;
age?: number;
}
const student1: Student = {}
// 報錯,name、age為必選屬性
// const student2: Required
4、Readonly
讓傳入類型中的所有屬性變成都是只讀的
interface Student {
name: string;
age: number;
}
const student1: Student = {
name: 'xumeng02',
age: 20
}
student1.age = 21
const student2: Readonly
name: 'xumeng03',
age: 20
}
// 報錯,屬性age只讀
// student2.age = 21
5、Pick
選擇傳入類型中的部分屬性組成新類型
interface Student {
name: string;
age: number;
}
const student1: Student = {
name: 'xumeng01',
age: 20
}
const student2: Pick
name: 'xumeng02'
}
const student3: Pick
name: 'xumeng03',
// 報錯,Pick
// age: 20
}
const student4: Pick
name: 'xumeng04',
age: 20
}
6、Exclude
針對聯(lián)合類型,排除相同的,留下不同的
type PersonAttr = 'name' | 'age'
type StudentAttr = 'name' | 'age' | 'class' | 'school'
const student1: Exclude
7、Extract
針對聯(lián)合類型,排除不同的,留下相同的
type PersonAttr = 'name' | 'age'
type StudentAttr = 'name' | 'age' | 'class' | 'school'
const student1: Extract
8、Omit
傳入一個類型,和這個類型的幾個屬性,把傳入的屬性省略掉,組成一個新類型
interface Student {
name: string;
age: number;
class: string;
school: string;
}
export type PersonAttr = 'name' | 'age'
const student1: Omit
class: '',
school: ''
}
9、NonNullable
不能為空
type k = string | null | undefined
// 報錯,不能為空
// let p: NonNullable
// 報錯,不能為空
// let p: NonNullable
10、Parameters
獲取傳入函數(shù)的參數(shù)組成的元組類型
interface StudentFunc {
(name: string, age: number): string
}
const student1: Parameters
11、ConstructorParameters
獲取傳入構造函數(shù)的參數(shù)組成的元組類型
class Student {
name: string;
age: number;
}
const student1: ConstructorParameters
12、ReturnType
獲取傳入函數(shù)的返回類型
class Student {
name: string;
age: number;
}
const student1: ReturnType<(name: string, age: number) => Student> = {
name: 'xumeng03',
age: 22
}
13、InstanceType
獲取傳入構造函數(shù)的返回類型
class Student {
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name
this.age = age
}
}
const student1: InstanceType
name: 'xumeng03',
age: 22
}
14、Uppercase
type StudentSexType = 'male' | 'female'
const studentSex: Uppercase
15、Lowercase
type StudentSexType = 'MALE' | 'FEMALE'
const studentSex: Lowercase
16、Capitalize
type StudentSexType = 'male' | 'female'
const studentSex: Capitalize
17、Uncapitalize
type StudentSexType = 'MALE' | 'FEMALE'
const studentSex: Uncapitalize
2.11、infer
1、類型推斷
type k
const a: k
2、類型提取
type arr = ['a', 'b', 'c']
type p1
type p2
const b1: p1
const b2: p2
3、遞歸
type arr = ['a', 'b', 'c']
type rever
const a: rever
3、泛型
3.1、定義
// 接口中使用泛型
interface fun4
id: T
}
let data1: fun4
id: 1
}
// 方法中使用泛型
const fun2 = function
return param
}
console.log(fun2
console.log(fun2
// type中使用泛型
type IFun =
const fun3: IFun = (param) => {
return param
}
console.log(fun3
console.log(fun3
3.2、泛型默認值
const fun4 =
return param
}
console.log(fun4("xumeng03"));
3.3、泛型約束
// 泛型約束
const fun5 = function
return param1 + param2;
}
console.log(fun5
// console.log(fun5
type I1 = {
age: number
}
const fun6 = function
return param.age
}
type I2 = {
name: string
age: number
}
const fun7 = function
return param[key]
}
console.log(fun7({name: "xumeng03", age: 23}, "name"));
console.log(fun7({name: "xumeng03", age: 23}, "age"));
type I3
const fun8 = function
return param[key]
}
3.4、泛型抽離
type I3
const fun8 = function
return param[key]
}
3.5、條件分發(fā)
type Code
type icode1 = Code<200>
type icode2 = Code<201>
type Code1
type icode3 = Code1<201, number>
type icode4 = Code1<201, string>
type I4
const fun9 = function
return param1 + (param2 as any);
}
type I5
// 涉及到泛型時會進行類型分發(fā)(string | number)
type type1 = I5
// 直接使用不會進行類型分發(fā)(string)
type type2 = (string | number) extends number ? number : string;
避免條件分發(fā)
// 避免條件分發(fā)
type I6
type type3 = I6
判斷條件分發(fā)是否相等
// 判斷條件分發(fā)是否相等
type I7
type type4 = I7
type type5 = I7
獲取兩個類型交集
// 獲取兩個類型交集
type I8 = Extract
排除兩個類型交集
// 排除兩個類型交集
type I9 = Exclude
判斷非空
let e = document.getElementById("app")
type I10 = NonNullable
3.6、類型推斷
// 類型推斷
function fun1(param1: string, param2: number) {
return {param1, param2}
}
type t1 = typeof fun1;
// type ReturnType
// type ReturnType
type t2 = ReturnType
function fun2(param1: string, param2: number) {
return {param1, param2}
}
type ReturnType1
type t3 = ReturnType1
4、命名空間
在最新的TypeScript版本中,推薦使用ES模塊(ES Modules)作為模塊化的解決方案,而不是過度使用命名空間
// 命名空間
namespace Zoo {
export let name: string
export class Dog{}
}
console.log(Zoo.name, Zoo.Dog)
namespace Home {
export let name: string
export class Dog{}
}
console.log(Home.name, Home.Dog)
5、tsconfig.json
{
// 編譯選項
"compilerOptions": {
// 編譯時會生成一個緩存文件,第二次編譯會讀取緩存文件,加快編譯速度
"incremental": true,
// 緩存文件位置
"tsBuildInfoFile": ".tsbuildinfo",
// 打印編譯信息
"diagnostics": false,
// 目標語言的版本
"target": "ES6",
// 生成代碼的·模板·標準
"module": "ES6",
// ts使用的庫
// "lib": [],
// 允許編譯js
// "allowJs": false,
// 允許js報錯,一般與allowJs一起使用
// "checkJs": false,
// 指定輸出目錄
"outDir": "./dist",
// 指定文件目錄
"rootDir": "./",
// 自動生成聲明文件
"declaration": true,
// 指定生成文件位置
"declarationDir": "",
// 生成聲明文件的sourcemap
"declarationMap": false,
// 生成目標文件的sourcemap
"sourceMap": false,
"inlineSourceMap": false,
// 第三方聲明文件的放置位置
"typeRoots": [],
"types": [],
// 刪除注釋
"removeComments": true,
// 編譯后不產生js文件
"noEmit": false,
// 編譯發(fā)生錯誤不會輸出js文件
"noEmitOnError": true,
// 遍歷器降級
"downlevelIteration": false,
// 開啟所有嚴格的類型檢查
"strict": true,
// 嚴格模式下為文件頭部注入"use strict"
"alwaysStrict": true,
// 不允許隱式的any
"noImplicitAny": true,
// 不允許把null、undefined賦值給其他變量
"strictNullChecks": true,
// 不允許函數(shù)雙向協(xié)變
"strictFunctionTypes": false,
// 類的實例屬性必須初始化
"strictPropertyInitialization": false,
// 嚴格檢查Bind、Call、Apply類型
"strictBindCallApply": true,
// 不允許this有隱式的any類型
"noImplicitThis": false,
// 檢查未使用的局部變量
"noUnusedLocals": false,
// 檢查未使用的函數(shù)參數(shù)
"noUnusedParameters": false,
// 放置switch語句貫穿(沒有break)
"noFallthroughCasesInSwitch": false,
// 模塊編譯策略
"moduleResolution": "classic",
// 解析非相對模塊的基地址
"baseUrl": "./",
// js語法的解析器
"jsxFactory": "React.createElement",
// jsx解析器
"jsx": "preserve",
// 路徑映射
"paths": {
// 手動指定json5版本
"@json5": [
"node_modules/json5/dist/index.min.js"
]
}
},
// 指定編譯目錄
"include": [
"src/**/*"
],
// 編譯排除目錄
"exclude": [],
// 指定文件使用該配置
"files": []
}
6、聲明文件
常用于第三方庫沒有聲明文件時時候
declare const xumeng: string;
7、裝飾器
tsconfig中compilerOptions的experimentalDecorators需要設置為true
裝飾器的執(zhí)行時機,不是在創(chuàng)建實例的時候運行,而是在類創(chuàng)建的時候就會執(zhí)行 裝飾器對類的行為的改變,是代碼編譯時發(fā)生的,而不是在運行時。這意味著,裝飾器能在編譯階段運行代碼
7.1、類裝飾器
// 類裝飾器
const Xuehua: ClassDecorator = (target) => {
// target代表class Xue
console.log(target);
target.prototype.name = "xumeng03"
target.prototype.helloworld = () => {
return "hello world!"
}
}
@Xuehua
class Xue {
constructor () {
}
// ......
}
const xue = new Xue() as any
console.log(xue.name,xue.helloworld())
7.2、裝飾器工廠
// 裝飾器工廠
const Fun = (name: string): ClassDecorator => {
return (target) => {
// target代表class Xue
console.log(target);
target.prototype.name = name
target.prototype.helloworld = () => {
return "hello " + name + '!';
}
}
}
@Fun("xumeng03")
class Xue {
constructor() {
}
// ......
}
const xue = new Xue() as any
console.log(xue.name, xue.helloworld())
7.3、多裝飾器
// 裝飾器工廠
const Fun = (name: string): ClassDecorator => {
return (target) => {
// target代表class Xue
console.log(target);
target.prototype.name = name
target.prototype.helloworld = () => {
console.log("hello " + name + '!')
}
}
}
const Fun2 = (name: string): ClassDecorator => {
return (target) => {
// target代表class Xue
console.log(target);
target.prototype.name1 = name
target.prototype.helloworld1 = () => {
console.log("hello " + name + '!')
}
}
}
// 執(zhí)行順序由下到上
@Fun("xumeng03")
@Fun2("xumeng")
class Xue {
constructor() {
}
// ......
}
const xue = new Xue() as any
7.4、函數(shù)裝飾器
const Fun = (name: string): MethodDecorator => {
return (target, key, descriptor: PropertyDescriptor) => {
// target代表class Xue
console.log(target, key, descriptor, name);
// ......
descriptor.value(name)
}
}
class Xue {
constructor() {
}
@Fun("xumeng03")
getName(data: string): void {
console.log('hello ' + data + '!')
}
}
const xue = new Xue();
7.5、參數(shù)裝飾器
待補。。。
7.6、屬性裝飾器
待補。。。
8、逆變&協(xié)變&雙向協(xié)變
// 協(xié)變(變量)
class Biology {
id: number
}
class Person extends Biology {
name: string
}
let b: Biology
let p: Person = {
id: 2,
name: "xumeng03"
}
b = p
// 逆變(函數(shù))
let b1 = (param1: Biology) => {
}
let p1 = (param1: Person) => {
}
// 報錯
// b1=p1
p1=b1
// 雙向協(xié)變(tsconfig中compilerOptions的strictFunctionTypes需要設置為false)
let b1 = (param1: Biology) => {
}
let p1 = (param1: Person) => {
}
// 不再報錯
b1=p1
p1=b1
柚子快報邀請碼778899分享:TypeScript學習筆記
好文推薦
本文內容根據(jù)網(wǎng)絡資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。
轉載請注明,如有侵權,聯(lián)系刪除。