# TSCode **Repository Path**: su27sk/TSCode ## Basic Information - **Project Name**: TSCode - **Description**: 学习TypeScript的基本语法已经装饰器相关内容,为后期学习Ts版本的Vue3做好铺垫 - **Primary Language**: TypeScript - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-02-06 - **Last Updated**: 2026-02-09 ## Categories & Tags **Categories**: Uncategorized **Tags**: 前端 ## README ## TypeScript部分 ### 意外收获 - 步骤 1:以管理员身份运行 PowerShell 按下 Win 键,输入 PowerShell 右键点击「Windows PowerShell」,选择「以管理员身份运行」 - 步骤 2:查看当前执行策略 在管理员权限的 PowerShell 中输入以下命令并回车: powershell Get-ExecutionPolicy 你大概率会看到输出是 Restricted(这是默认值,禁止运行任何脚本)。 - 步骤 3:修改执行策略 输入以下命令来设置允许运行本地脚本(最安全且能解决问题的配置): powershell Set-ExecutionPolicy RemoteSigned 执行后会弹出确认提示,输入 Y 并回车确认 这个策略的含义:本地创建的脚本可以运行,从网络下载的脚本必须有数字签名才能运行 - 步骤 4:验证修改是否生效 再次输入以下命令验证: powershell Get-ExecutionPolicy 如果输出是 RemoteSigned,说明修改成功。 ### Js存在的不足 ``` // 1.不清不楚的数据类型 let welcome = 'hello' welcome() // 2.有漏洞的逻辑 const str = Date.now() % 2 ? "奇数" : "偶数" if(str !== '奇数') { alert('hello') } else if(str === '偶数'){ alert('world') } // 3.访问不存在的属性 const obj = {width:10,height:15}; const area = obj.heigth * obj.width; // 4.低级拼写错误 const message = 'hello,world' message.toUperCase() ``` ### Ts命令行编译 npm i typescript -g 全局下载ts指令 tsc index 将index.ts文件转换为js ### Ts自动化编译 tsc --inits # 初始化tsconfig.json配置文件 tsc --watch # 实时监控将ts编译为js ``` "noEmitOnError":true, # 有错误不编译 "sourceMap": false, # 不生成其他编译 "declaration": false, "declarationMap": false, ``` ### 数据类型 - any ``` let a:any // 显式any a = 99 a = 'hello' a = false let b b = 99 b = 'world' b = false let x:string x = a console.log(x); // any可以赋值给任何类型 ``` - unknown ``` let a:unknown a = 99 a = false a = 'hello' let x:string // x = a // 第一种赋值方式 if(typeof a === "string") { x = a } // 断言 x = a as string // 断言 x = a let str3 :unknown str3 = 'hello'; (str3 as string).toUpperCase() console.log(str3); ``` - never ``` // never function demo():never{ throw new Error('程序运行异常') } let x = demo() console.log(x); // never一般是程序自己推断出来的,实际开发很少有 let a :string a = 'hello' if(typeof a === 'string') { console.log(a.toUpperCase()); } else{ console.log(a); } ``` - void ``` // void function logMessage(msg:string):void { console.log(msg); } function logMessage2(msg:string):void { console.log(msg); return } function logMessage3(msg:string):void { console.log(msg); return undefined } logMessage('你好') logMessage2('你好') logMessage3('你好') ``` - Object ``` // object let a:object // 只能声明非原始类型 let b:Object // 除了null,和 undefined都能声明 // 声明对象类型 let person: { name:string; age?:number; // 创建对象这个属性可有可无 [key:string]:any // 索引签名 } person = {name:'tom',age:18,gender:'男',city:'北京'} console.log(person); // 声明函数类型 let count:(a:number,b:number) => number count = function(a,b) { return a + b } console.log(count(1,2)); // 声明数组类型 let arr1:string[] let arr2:Array arr1 = ['1','2','3'] arr2 = [1,2,3] console.log(arr1,arr2); ``` - tuple元组 ``` // tuple元组 let arr1 : [string,number] let arr2 : [string,boolean?] let arr3 : [number,...string[]] arr1=['hello',10] arr2=['hello',false] arr3=[1,'a','b','c'] ``` - eunm 枚举 ``` // eunm 枚举 const enum Direction { Up, Down, Left, Right } function walk(data:Direction) { if(data === Direction.Up) { console.log("1"); } else if(data === Direction.Down){ console.log("2"); } else if(data === Direction.Left) { console.log("3"); } else if(data === Direction.Right){ console.log("4"); }else { console.log("5"); } } walk(Direction.Up) ``` - type ``` // type // 基础类型 type Username = string; let name1 :Username = 'zs' console.log(name1); // 联合类型 type Status = number | string type Gender = '男' | '女' function prinntStatus(data:Status):void { console.log(data); } function printGender(data:Gender):void { console.log(data); } prinntStatus('404') prinntStatus(404) printGender('男') printGender('女') // 交叉类型 type Area = { height:number width:number } type Address = { num:number cell:number room:string } type House = Area & Address const house : House = { height:100, width:100, num:1, cell:2, room:'404' } console.log(house); ``` ### 特殊情况 ``` // 特殊情况 function demo():void { return undefined } demo() type LogFunc =() => void const f1 : LogFunc = function() { return 66 } const f2 : LogFunc = () => 666 const f3 : LogFunc =function() { return "" } let x = f1() console.log(x); ``` ### 复习一下类 ``` class Person { name:string age:number constructor(name:string,age:number){ this.name = name this.age = age } speak() { console.log(`我叫:${this.name},今年${this.age}岁`); } } class Student extends Person { grade:string constructor(name:string,age:number,grade:string) { super(name,age) this.grade = grade } study(){ console.log(`${this.name}正在努力学习中~~~`); } override speak(): void { console.log(`我是学生,我叫:${this.name},今年${this.age}岁,在读${this.grade}`); } } const s1 = new Person('张三',13) s1.speak() const s2 = new Student('李同学',16,'高三') s2.study() s2.speak() ``` ### 属性修饰符 ![png.png](pic/png.png) - 简写形式 ``` class Person { constructor(public name:string, public age:number){ } } ``` ### 抽象类/抽象方法 ``` // 抽象类/抽象方法 abstract class Package { // 构造方法 constructor(public weight:number) {} // 抽象方法 abstract calculate():number // 具体方法 printPackage() { console.log(`包裹的重量为:${this.weight}kg,运费为${this.calculate()}元`); } } class StandardPackage extends Package { constructor( weight:number, public unitPrice: number ){super(weight)} calculate(): number { return this.weight * this.unitPrice } } class ExpressPackage extends Package { constructor( weight:number, public unitPrice: number, public additional: number ){ super(weight) } calculate(): number { if(this.weight > 10){ return 10 * this.unitPrice + (this.weight - 10) * this.additional }else{ return this.weight * this.unitPrice } } } const s1 = new StandardPackage(10,5) console.log(s1.calculate()); s1.printPackage() const s2 = new ExpressPackage(10,7,8) console.log(s2.calculate()); s2.printPackage() ``` ### 接口 ``` // 接口 // 定义类 interface PersonInterface { name:string age:number speak(n:number):void } class Person implements PersonInterface { constructor( public name:string, public age:number ){} speak(n: number): void { for(let i = 0;i void } const user : UserInterface = { name:'张三', gender:'男', run(n) { console.log(`跑了${n}米`); } } // 定义函数 interface CountInterface { (a:number,b:number):number } const count :CountInterface = (x,y)=>{ return x + y } // 接口之间是可以继承的 interface PersonInterface { name:string // 姓名 age:number // 年龄 } interface StudentInterface extends PersonInterface { grade: string // 年级 } const stu:StudentInterface = { name:"zhangsan", age:18, grade:"初二" } // 接口的自动合并 interface PersonInterface { name:string // 姓名 age:number // 年龄 } interface PersonInterface { gender: string } const p:PersonInterface = { name:'tom', age:18, gender:"男" } ``` ### 泛型 ``` // 泛型 // 泛型函数 /* function logData (data:T) { console.log(data); } logData(100) logData("hello") */ // 泛型可以有多个 /* function logData2(data1:T,data2:U): T | U { return Date.now() % 2 ?data1 : data2 } console.log(logData2(60,true)); */ // 泛型接口 /* interface PersonInterface { name:string; age:number; extraInfo:T } type JobInfo = { title:string; company:string } let p :PersonInterface = { name:'tom', age:18, extraInfo:{ title:"111", company:"111" } } console.log(p); */ // 泛型类 /* class Person { constructor( public name:string, public age:number, public extraInfo:T ){} speak(){ console.log(`我叫${this.name},今年${this.age}`); console.log(`${this.extraInfo}`); } } type JobInfo = { title:string; company:string } const p = new Person("tom",12,{ title:"111",company:"111"}) console.log(p); */ ``` ### 类型声明文件 为了在ts里面调用js demo.js ``` export function add(a,b) { return a+b } export function mul(a,b){ return a*b } ``` demo.d.ts ``` declare function add(a:number,b:number):number; declare function mul(a:number,b:number):number; export{add,mul} ``` index.ts ``` // 类型声明文件 import {add,mul} from './demo.js' console.log(add(1,2)); console.log(mul(3,4)); ``` ## 装饰器部分 ### 配置部分 修改tsconfig.json文件里面的配置 ``` "experimentalDecorators":true // 开启装饰器 ``` ### 类装饰器 - 初步了解 TS 装饰器是一种特殊的函数,可以附加到类、方法、属性、参数上,用来在不修改原代码的前提下,给目标添加额外功能 / 修改行为—— 本质是 “包装器”,核心作用是 “扩展 / 修改目标的行为”。 ``` // 1.初步认识装饰器,Demo是一个装饰器在Person类定义的时候执行 function Demo(target:Function){ console.log(target); } @Demo class Person { constructor( public name:string, public age:number ){} } const p1 = new Person('张三',18) console.log(p1.toString()); ``` - 替换被装饰的类 ``` // 保证泛型的要求 type Constrctor = new (...args: any[]) => {} // 接口合并,添加新属性或者方法 interface Person { getTime():void } function LogTimez(target: T) { return class extends target{ createTime:Date constructor(...args: any[]) { super(...args) this.createTime = new Date() } getTime(){ return `该对象的创建时间是${this.createTime}` } } } @LogTimez class Person { name:string age:number constructor(name:string,age:number){ this.name = name this.age = age } speak(){ console.log('你好啊!!!'); } } const p1 = new Person('张三',18) console.log(p1); console.log(p1.getTime()); ``` ### 装饰器工厂 ``` // 构建装饰器工厂,在工厂里面返回一个装饰器,可以携带一些参数进去 function LogInfo(num:number) { return function(target:Function) { target.prototype.introduce = function(){ for(let i = 1 ; i<= num ;i++) { console.log(`我的名字:${this.name},我的年龄${this.age}`); } } } } @LogInfo(3) class Person { constructor( public name:string, public age:number ){} speak(){ console.log('你好啊!!!'); } } const p1 = new Person('张三',18) p1.introduce() ``` ### 装饰器组合 ``` function test1(target:Function) { console.log('test1'); } function test2() { console.log('test2工厂'); return function(target:Function) { console.log('test2'); } } function test3() { console.log('test3工厂'); return function(target:Function) { console.log('test3'); } } function test4(target:Function) { console.log('test4'); } @test1 @test2() @test3() @test4 class Person{} ``` ### 属性装饰器 ``` // 属性装饰器 function Demo (target:object,propertyKey:string) { console.log(target,propertyKey); } // 关于一个相应式的真实应用案例 function State (target:object,propertyKey:string) { let key = `__${propertyKey}` Object.defineProperty(target,propertyKey,{ get(){ return this[key] }, set(newValue){ console.log(`${propertyKey}的最新值为:${newValue}`); this[key] = newValue }, enumerable:true, configurable:true }) } // 属性装饰器 /* target:对于静态属性来说值是类,对于实例属性来说值是类的原型对象。 propertyKey:属性名。 */ class Person { @Demo name:string; @State age: number; @Demo static school:string constructor (name:string,age:number){ this.name = name this.age = age } } const p1 = new Person("张三",18) const p2 = new Person("李三",28) p1.age = 30 p2.age = 40 console.log(p1.age); console.log(p2.age); ``` ### 方法装饰器 ``` // 函数装饰器 function Demo(target:any,propertyKey:string,descriptor:any) { console.log(target,propertyKey,descriptor); } // 使用函数装饰器完成一个打印日志功能 function Logger(target:any,propertyKey:string,descriptor:PropertyDescriptor) { // 储存原始方法 const original = descriptor.value // 替换原有方法 descriptor.value = function(...args:any[]) { console.log(args instanceof Array); console.log(`${propertyKey}开始执行`); const result = original.call(this,...args) console.log(`${propertyKey}执行完毕`); return result } } class Person { constructor( public name:string, public age:number, ){} @Logger speak(str:string){ console.log(`你好,我的名字${this.name},${str}`); } @Demo static isAdult(age:number){ return age >= 18 } } const p1 = new Person('张三',18) p1.speak("hello") ``` ### 访问器装饰器 ``` // 访问器装饰器 function RangeValidate(min:number,max:number) { return function (target:any,propertyKey:string,descriptor:PropertyDescriptor){ // 保持原有set const originalSetter = descriptor.set // 参数检查 descriptor.set = function(value:number) { if(value < min || value > max) { throw new Error(`${propertyKey}应该在${min}与${max}之间`) } if(originalSetter){ originalSetter.call(this,value) } } } } class weather { constructor( private _temp:number ){ } get temp(){ return this._temp } @RangeValidate(-50,50) set temp(value){ this._temp = value } } const w1 = new weather(50) //console.log(w1.temp = 90); console.log(w1.temp = 40); ```