TypeScript 使用手册
编译TypeScript
TIP
浏览器不能直接运行 TypeScript 代码,需要编译为 JavaScript 再交由浏览器解析器执行
命令行编译
- 全局安装 TypeScriptbash
$ npm install typescript -g
- 使用命令编译.ts文件bash
$ tsc demo.ts
自动化编译
- 创建 TypeScript 编译控制文件bash
$ tsc --init
- 监视目录中的.ts文件变化bash
$ tsc --watch
- 小优化,当编译出错时不生产.js文件bash
$ tsc --noEmitOnError --watch
常用类型与语法
any
any
的含义是任意类型,一旦将变量类型限制为any
,那就意味着放弃了对该变量的类型检查
// 明确的表示a的类型是 any 【显式的any】
let a = any
a = 100
a = false
a = '你好'
// 没有明确表示b的类型是 any 【隐式的any】
let b
b = 100
b = false
b = '你好'
unknown
unknown
的含义是:未知类型
unknown
可以理解为一个类型安全的any
,适用于:不确定数据的具体类型ts// 设置a的类型为unknown let a: unknown a = 100 a = false a = '你好' // 设置x的数据类型为string let x: string x = a // 警告:不能将类型unknown分配给类型string
unknown
会强制开发者在使用之前进行类型检查,从而提供更强的类型安全性tslet a: unknown a = 'hello' // 第一种方式:加类型判断 if (typeof a === 'string') { x = a console.log(x) } // 第二种方式:加断言 x = a as string // 第三种方式:加断言 x = <string>a
读取
any
类型数据的任何属性都不会报错,而unknown
正好与之相反tslet str1: any str1 = 'hello' str1.toUpperCase() // 无警告 let str2: unknown str2 = 'hello' str2.toUpperCase() // 警告:“str2”的类型为“未知”
never
never
的含义是:任何值都不是,简言之就是不能有值,undefined
、null
、""
、0
都不行!
几乎不用
never
去直接限制变量,因为没有意义,例如:ts// 指定a的类型为never,那就意味着a以后不能存任何的数据了 let a: never // 以下对a的所有赋值都会有警告 a = 1 a = true a = null a = undefined
never
一般是TypeScript主动推断出来的,例如:ts// 指定a的类型为string let a: string // 给a设置值 if (typeof a === 'string') { console.log(a.toUpperCase()) } else { console.log(a) // TS会推断出此处的a是never,因为没有任何一个值符合此处的逻辑 }
never
也可用于限制函数的返回值tsfunction throwError(str: string): never { throw new Error('程序异常退出:' + str) }
void
void 通常用于函数返回值声明,含义:【函数不返回任何值,调用者也不应依赖其返回值进行任何操作】
tsfunction logMessage(msg: string): void { console.log(msg) } logMessage('你好')
注意
编码者没有编写
return
去指定函数的返回值,所以logMessage
函数是没有显式返回值的,但会有一个 隐式返回值,就是undefined
;即:虽然函数返回类型为void
,但也可以接受undefined
的,简单记:undefined
是void
可以接受的一种“空”以下写法均符合规范
tsfunction logMessage1(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 }
那限制函数返回值时,是不是undefined和void就没区别呢?
有区别:【返回值类型为void的函数,调用者不应 依赖其返回值进行任何操作!】
对比如下代码:tsfunction logMessage(msg: string): void { console.log(msg) } let result = logMessage('你好') if (result) { // 此行报错,无法测试“void”类型的表达式的真实性 console.log('logMessage有返回值') }
tsfunction logMessage(msg: string): undefined { console.log(msg) } let result = logMessage('你好') if (result) { // 此行无警告 console.log('logMessage有返回值') }
总结
若函数返回类型为void,那么:
- 从语法上讲:函数是可以返回
undefined
的,至于显式返回,还是隐式返回,这无所谓! - 从语义上讲:函数调用者不应关心函数返回的值,也不应依赖返回值进行任何操作!即使返回了
undefined
值
- 从语法上讲:函数是可以返回
object
关于
object
与Object
,实际开发中用的相对较少,因为范围太大了
声明对象类型
实际开发中,限制一般对象,通常使用以下形式
ts// 限制person1对象必须有name属性,age为可选属性 let person1: { name: string; age?: number } // 含义同上,也能用分号分隔 let person2: { name: string; age?: number } // 含义同上,也能用换行分隔 let person3: { name: string age?: number }
索引签名:允许定义对象可以具有任意数量的属性,这些属性的键和类型是可变的,常用于:描述类型不确定的属性(具有动态属性的对象)
ts// 限制person对象必须有name属性,可选age属性但值必须是数字,同时可以有任意数量,任意类型的属性 let person: { name: string age?: number [key: string]: any // 索引签名,完全可以不用key这个单词,换成其他的也可以 } // 赋值合法 person = { name: 'bieber', age: 19, gender: '男' }
声明函数类型
let count: (a: number, b: number) => number
count = function (x, y) {
return x + y
}
- Typescript 中的
=>
在函数类型声明时表示函数类型,描述其参数类型和返回类型 - JavaScript 中的
=>
是一种定义函数的语法,是具体的函数实现 - 函数类型声明还可以使用:接口、自定义类型等方式。
声明数组类型
let arr1: string[]
let arr2: Array<number> // 泛型
arr1 = ['a', 'b', 'c']
arr2 = [100, 200]
tuple
TIP
元组(tuple)是一种特殊的数组类型,可以存储固定数量的元素,并且每个元素的类型是已知的且可以不同。元组用于精确描述一组值的类型。?
表示可选元素。
// 第一个元素必须是 string 类型,第二个必须是 number 类型
let arr1: [string, number]
// 第一个元素必须是 number 类型,第二个元素可选,如果有,必须是 boolean 类型
let arr2: [number, boolean?]
// 第一个元素必须是 number 类型,后面的元素可以是任意数量的 string 类型
let arr3: [number, ...string[]]
// 可以赋值
arr1 = ['hello', 123]
arr2 = [100, false]
arr2 = [200]
arr3 = [100, 'hello', 'world']
arr3 = [300]
// 不可以赋值, arr1声明时是两个元素,赋值的是三个
arr1 = ['hello', 123, false]
enum
枚举(enum)可以定义一组命名常量,它能增强代码的可读性,也让代码更好维护
如下代码:这种情况是适合用枚举
function walk(str: string) {
if (str === 'up') {
console.log('向【上】走')
} else if (str === 'down') {
console.log('向【下】走')
} else if (str === 'left') {
console.log('向【左】走')
} else if (str === 'right') {
console.log('向【右】走')
}
}
walk('up')
walk('down')
walk('left')
walk('right')
数字枚举
数字枚举一种常见的枚举类型,其成员的值会自动递增,且数字枚举还具备反向映射的特点, 在下面代码的打印中,可以发现:可以通过值来获取对于的枚举成员名称
tsenum Direction { Up, Down, Left, Right } console.log(Direction) // 输出: {0:"up", 1:"Down", 2:"Left", 3:"Right",Up:0,Donw:1,Left:2,Right:3} console.log(Direction.Down)
优化例子中的代码
tsenum Direction { Up, Down, Left, Right } function walk(n: Direction) { if (n === Direction.Up) { console.log('向【上】走') } else if (n === Direction.Down) { console.log('向【下】走') } else if (n === Direction.Left) { console.log('向【左】走') } else if (n === Direction.Right) { console.log('向【右】走') } } // 执行 walk(Direction.Right)
字符串枚举
枚举成员的值是字符串,但没有了反向映射的特点
tsenum Direction{ Up = "up" Down = "down" Left = "left" Right = "right" }
常量枚举
官方描述:常量枚举是一种特殊枚举类型,它使用const 关键字定义,在编译时会被内联,避免生成一些额外的代码。
ts// const 很关键 const enum Direction { Up, Down, Left, Right } console.log(Direction.Up)
type
type 可以为任意类型创建别名,让代码更简洁,可读性更强,同时能更方便的进行类型复用和扩展
基本用法
类型别名使用
type
关键字定义,type
后跟类型名称,例如下面代码中num
时类型别名tstype num = number let price: num price = 100
联合类型
联合类型时一种高级类型,它表示一个值可以是几种不同类型之一
tstype Status = number | string type Gender = '男' | '女' function printStatus(status: Status) { console.log(status) } function logGender(str: Gender) { console.log(str) } printStatus(404) printStatus('200') logGender('男') logGender('女')
交叉类型
交叉类型允许将多个类型合并为一个类型,合并后的类型将拥有所有被合并类型的成员。交叉类型通常用于对象类型
ts// 面积 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: 3, cell: 4, room: '702' }
属性修饰符
修饰符 | 含义 | 具体规则 |
---|---|---|
public | 公开的 | 可以被:类内部、子类、类外部访问 |
protected | 受保护的 | 可以被:类内部、子类访问 |
private | 私有的 | 可以被:类内部访问 |
readonly | 只读属性 | 属性无法修改 |
abstract(抽象类)
概念理解
抽象类不能实例化,其意义是可以被继承,抽象类里可以有普通方法,也可以有抽象方法
通过一下场景,理解抽象类:
定义一个抽象类 Package,表示所有包裹的基本结构,任何包裹都有重要属性 weight,包裹都需要计算运费。 但不同类型的包裹,(如:标准速度、特快专递)都有不同的运费计算方式,因此用于计算运费的 calculate 方法 是一个抽象方法,必须有具体的子类来实现
Package 类
abstract class Package {
// 构造方法
constructor(public weight: number) {}
// 抽象方法
abstract calculate(): number
// 具体方法
printpackage() {
console.log(`包裹重量为:${this.weight}kg,运费为:${this.calculate()}元`)
}
}
StandardPackage 类(标准包裹)
class StandardPackage extends Package {
constructor(
weight: number,
public unitPrice: number
) {
super(weight)
}
calculate(): number {
return this.weight * this.unitPrice
}
}
const s1 = new StandardPackage(10, 5)
s1.printpackage()
ExpressPackage 类(特快包裹)
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 e1 = new ExpressPackage(13, 8, 2)
e1.printpackage()
总结:何时使用抽象类?
- 定义通用接口:为一组相关的类定义通用的行为(方法或属性)时
- 提供基础实现:在抽象类中提供某些方法或为其提供基础实现,这样派生类就可以继承这些实现
- 确保关键实现:强制派生类实现一些关键行为
- 共享代码和逻辑:当多个类需要共享部分代码时,抽象类可以避免代码重复
一些相似概念的区别
interface 与 type 的区别
TIP
- 相同点:
interface
和type
都可以用于定义对象结构,两者在许多场景中是可以互换的。 - 不同点:
interface
:更专注于定义对象和类的结构,支持继承、合并type
:可以定义类型别名、联合类型、交叉类型,但不支持继承和自动合并
interface 和 type 都可以定义对象结构
tsinterface PersonInterface { name: string age: number speak(): void } type PersonType = { name: string age: number speak(): void } const p1: PersonInterface = { name: 'Tom', age: 19, speak() { console.log(this.name) } } const p2: PersonType = { name: 'Tom', age: 19, speak() { console.log(this.name) } }
interface 可以集成、合并
tsinterface PersonInterface { name: string age: number } interface PersonInterface { speak: () => void } interface StudentInterface extends PersonInterface { grade: string // 年级 } const student: StudentInterface = { name: '张三', age: 18, grade: '高二', speak() { console.log(this.name, this.age, this.grade) } }
type的交叉类型
ts// 使用 type 定义 Person 类型,并通过交叉类型实现属性的合并 type PersonType = { name: string age: number } & { speak: () => void } // 使用 type 定义 Student 类型,并通过交叉类型继承 PersonType type StudentType = PersonType & { grade: string } const student: StudentType = { name: '张三', age: 18, grade: '高二', speak() { console.log(this.name, this.age, this.grade) } }
- 相同点:
interface 与 抽象类的区别
TIP
- 相同点:都用于定义一个类的格式
- 不同点:
- 接口:只能描述结构,不能有任何实现代码,一个类可以实现多个接口
- 抽象类:既可以包含抽象方法,也可以包含具体方法,一个类只能继承一个抽象类
一个类可以实现多个接口
ts// FlyInterface接口 interface FlyInterface { fly(): void } // SwimInterface接口 interface SwimInterface { swim(): void } // Duck 类实现了 FlyInterface 和 SwimInterface 两个接口 class Duck implements FlyInterface, SwimInterface { fly(): void { console.log('鸭子可以飞') } swim(): void { console.log('鸭子可以游泳') } } // 创建一个 Duck 实例 const duck = new Duck() duck.fly() // 输出:鸭子可以飞 duck.swim() // 输出:鸭子可以游泳
泛型
概念
泛型允许我们在定义函数、类或接口时,使用类型参数来表示未指定的类型,这些参数在具体使用时,才被指定具体的类型
泛型能让同一段代码适用于多种类型,同时仍然保持类型的安全性
举例:如下代码中<T>
就是泛型(不一定非叫T
),设置泛型后即可在函数中使用T
来表示该类型
泛型函数
function logData<T>(data: T) {
console.log(data)
}
logData<number>(100)
logData<string>('hello')
泛型可以有多个
function logData<T, U>(data1: T, data2: U): T | U {
console.log(data1, data2)
return Date.now() % 2 ? data1 : data2
}
logData<number, string>(100, 'hello')
logData<string, boolean>('ok', false)
泛型接口
interface PersonInterface<T> {
name: string
age: number
extraInfo: T
}
let p1: PersonInterface<string>
let p2: PersonInterface<number>
p1 = { name: '张三', age: 19, extraInfo: '一个好人' }
p2 = { name: '李四', age: 13, extraInfo: 350 }
泛型约束
interface PersonInterface {
name: string
age: number
}
function logPerson<T extends PersonInterface>(info: T): void {
console.log(`我叫${info.name},今年${info.age}岁了`)
}
logPerson({ name: '张三', age: 19 })
泛型类
class Person<T> {
constructor(
public name: string,
public age: number,
public extraInfo: T
) {}
speak() {
console.log(`我叫${this.name},今年${this.age}岁了`)
console.log(this.extraInfo)
}
}
// 测试代码1
const p1 = new Person<number>('tom', 30, 240)
// 测试代码2
type JobInfo = {
title: string
company: string
}
const p2 = new Person<JobInfo>('tom', 30, { title: '研发总监', company: 'XXX科技公司' })
类型声明文件
说明
类型声明文件是 TypeScript 中的一种特殊文件,通常以 .d.ts 作为扩展名。
它的主要是作用是为现有的Javascript代码提供类型信息,使得TypeScript能够在使用这些Javascript库或模块时进行 类型检查和提示
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))
装饰器
提醒
虽然 TypeScript5.0
中可以直接使用类装饰器,但为了确保其他装饰器可用,现阶段使用时,仍建议使用 experimentalDecorators
配置来开启装饰器支持,而且不排除在未来的版本中,官方会进一步调整装饰器的相关语法
类装饰器
基本语法
类装饰器是一个应用在类声明上的函数,可以为类添加额外的功能,或添加额外的逻辑
基本语法
tsfunction Demo(target: Function) { console.log(target) } @Demo // 与Demo(Person)等价 class Person { constructor( public name: string, public age: number ) {} }
应用举例
需求:定义一个装饰器,实现 Person 实例调用 toString 时返回 JSON.stringify 的执行结果
应用举例
ts// 使用装饰器重写toString方法 + 封闭其原型对象 function CustomString(target: Function) { // 向被装饰类的原型上添加自定义的 toString 方法 target.prototype.toString = function () { return JSON.stringify(this) } // 封闭其原型对象,禁止随意操作其原型对象 Object.seal(target.prototype) } @CustomString class Person { constructor( public name: string, public age: number ) {} speak() { console.log('你好!') } } const p1 = new Person('bieber', 10) console.log(p1.toString())
关于返回值
关于
类装饰器有返回值:若类装饰器返回一个新的类,那这个新类将替换掉被装饰的类
类装饰器无返回值:若类装饰器无返回值或返回 undefined,那被装饰的类不会被替换关于返回值
tsfunction demo(target: Function) { // 装饰器有返回值时,该返回值会替换被装饰的类 return class { test() { console.log(200) console.log(300) console.log(400) } } } @demo class Person { test() { console.log(100) } } console.log(Person)
关于构造类型
仅声明构造类型
ts/* new 表示:该类型是可以用new操作符调用 ...args 表示:构造器可以接受【任意数量】的参数 any[] 表示:构造器可以接受【任意类型】的参数 {} 表示:返回类型是对象(非null、非undefined的对象) */ type Constructor = new (...args: any[]) => {} function test(fn: Constructor) {} class Person {} test(Person)
声明构造类型 + 指定静态属性
tstype Constructor = { new (...args: any[]): {} wife: string } // 需求是fn得是一个类 function test(fn: Constructor) {} class Person { static wife: string } test(Person)
替换被装饰的类 对于高级一些的装饰器,不仅仅是覆盖一个原型上的方法,还要有更多功能,例如添加新的方法和状态
需求:设计一个 LogTime 装饰器,可以给实例添加一个属性,用于记录实例对象的创建时间,再添加一个方法用于读取创建时间
tstype Constructor = new (...args: any[]) => {} interface Person { getTime(): void } function LogTime<T extends Constructor>(target: T) { return class extends target { createdTime: Date constructor(...args: any[]) { super(...args) this.createdTime = new Date() } getTime() { console.log(`该对象的创建时间是:${this.createdTime}`) } } } @LogTime class Person { constructor( public name: string, public age: number ) {} speak() { console.log('你好啊!') } } const p1 = new Person('bieber', 10) console.log(p1) console.log(p1.getTime())
装饰器工厂
装饰器工厂是一个返回装饰器函数的函数,可以为装饰器添加参数,可以更灵活地控制装饰器的行为。
需求:定义一个LogInfo类装饰器工厂,实现Person实例可以调用到introduce方法,且introduce中输出内容的次数, 由LogInfo接收的参数决定。
interface Person {
introduce(): void
}
// 装饰器工厂
function LogInfo(n: number) {
// 返回装饰器
return function (target: Function) {
target.prototype.introduce = function () {
for (let i = 0; i < n; 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('bieber', 19)
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 {}
装饰器组合--应用
interface Person {
introduce(): void
getTime(): void
}
// 装饰器
function CustomString(target: Function) {
target.prototype.toString = function () {
return JSON.stringify(this)
}
Object.seal(target.prototype)
}
// 装饰器工厂
function LogInfo(n: number) {
// 返回装饰器
return function (target: Function) {
target.prototype.introduce = function () {
for (let i = 0; i < n; i++) {
console.log(`我的名字:${this.name},我的年龄:${this.age}`)
}
}
}
}
// 装饰器
type Constructor = new (...args: any[]) => {}
function LogTime<T extends Constructor>(target: T) {
return class extends target {
createdTime: Date
constructor(...args: any[]) {
super(...args)
this.createdTime = new Date()
}
getTime() {
console.log(`该对象的创建时间是:${this.createdTime}`)
}
}
}
@CustomString
@LogInfo(5)
@LogTime
class Person {
constructor(
public name: string,
public age: number
) {}
speak() {
console.log('你好呀!')
}
}
const p1 = new Person('bieber', 19)
p1.speak()
console.log(p1.toString())
p1.introduce()
console.log(p1.getTime())
属性装饰器
基本语法
ts/* 参数说明: target:对于静态属性来说值是类,对于实例属性来说值是类的原型对象 propertyKey:属性名 */ function Demo(target: object, propertyKey: string) { console.log(target, propertyKey) } class Person { @Demo name: string @Demo age: number @Demo static school: string constructor(name: string, age: number) { this.name = name this.age = age } } const p1 = new Person('bieber', 19)
关于属性遮蔽
在如下代码中:当构造器中的
this.age = age
试图在实例上赋值时,实际上是调用了原型上age属性的set方法tsclass Person { constructor( public name: string, public age: number ) {} } let value = 90 // 使用defineProperty给Person原型添加age属性,并配置对应的get与set Object.defineProperty(Person.prototype, 'age', { get() { return value }, set(val) { value = val } }) const p1 = new Person('bieber', 19) console.log(p1.age) // 18 console.log(Person.prototype.age) // 18
应用举例
需求:定义一个
State
属性装饰器,来监视属性的修改tsfunction State(target: object, propertyKey: string) { const key = `__${propertyKey}` Object.defineProperty(target, propertyKey, { get() { return this[key] }, set(newValue) { console.log(`${propertyKey}的最新值为:${newValue}`) this[key] = newValue }, enumerable: true, configurable: true }) } class Person { name: string @State age: number constructor(name: string, age: number) { this.name = name this.age = age } } const p1 = new Person('bieber', 19) const p2 = new Person('李四', 20) p1.age = 30 p2.age = 40 console.log(p1, p2)
方法装饰器
基本语法
ts/* 参数说明: target:对于静态方法来说值是类,对于实例方法来说值是原型对象 propertyKey:方法的名称 descriptor:方法的描述对象,其中value属性是被装饰的方法 */ function Demo(target: any, propertyKey: any, descriptor: any) { console.log(target) console.log(propertyKey) console.log(descriptor) } class Person { constructor( public name: string, public age: number ) {} @Demo speak() { console.log(`你好,我的名字是:${this.name},我的年龄是${this.age}`) } @Demo static isAdult(age: number) { return age >= 18 } }
应用举例
需求:
1.定义一个 Logger 方法装饰器,用于在方法执行前和方法后,均追加一些额外逻辑
2.定义一个 Validate 方法装饰器,用于验证数据应用举例
tsfunction Logger(target: object, propertyKey: string, descriptor: PropertyDecorator) { // 存储原始方法 const originnal = descriptor.value // 替换原始函数 descriptor.value = function (...args: any[]) { console.log(`${propertyKey}开始执行.....`) const result = originnal.call(this, ...args) console.log(`${propertyKey}结束执行.....`) return result } } class Person { constructor( public name: string, public age: number ) {} @Logger speak() { console.log(`你好,我的名字是${this.name},我的年龄是${this.age}`) } static isAdult(age: number) { return age >= 18 } } const p1 = new Person('bieber', 18) p1.speak()
访问器装饰器
基本语法
ts/* 参数说明: target:对于实例访问器来说值是【所属类的原始对象】,对于静态访问器来说值是【所属类】 propertyKey:访问器的名称 descriptor:描述对象 */ function Demo(target: object, propertyKey: string, descriptor: PropertyDecorator) { console.log(target) console.log(propertyKey) console.log(descriptor) } class Person { @Demo get address() { return '北京朝阳区朝阳路' } @Demo static get country() { return '中国' } }
应用举例
需求:对
Weather
类的temp
属性的set 访问器进行限制,设置的最低温度 -50,最高温度 50应用举例
tsfunction RangeValidate(min: number, max: number) { return function (target: object, propertyKey: string, descriptor: PropertyDecorator) { 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 { private _temp: number constructor(_temp: number) { this._temp = _temp } @RangeValidate(-50, 50) set temp(value) { this._temp = value } get temp() { return this._temp } }
参数装饰器
基本语法
ts/* 参数说明: target: 1. 如果修饰的是【实例方法】的参数,target是类的【原型对象】 2. 如果修饰的是【静态方法】的参数,target是【类】 propertyKey:参数所在方法的名称 parameterIndex:参数在函数参数列表中的索引,从0开始 */ function Demo(target: object, propertyKey: string, parameterIndex: number) { console.log(target) console.log(propertyKey) console.log(parameterIndex) } // 类定义 class Person { constructor(public name: string) {} speak(@Demo message1: any, message2: any) { console.log(`${this.name}想对你说:${message1},${message2}`) } }
应用举例
需求:定义方法装饰器
Validate
,同时搭配参数装饰器NotNumber
,来对speak
方法的参数类型进行限制应用举例
ts...待补充