class
private 和 # 的区别
前缀 private 只是TS语法,在运行时不起作用,外部能够访问,但是类型检查器会报错
class Bag { private item: any }
修饰符 # 是JS语法,是运行时私有的,并且在JavaScript引擎内部强制执行,它只能在类内部访问
class Bag { #item: any }
修饰符?#,MDN 参考链接: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Classes/Private_class_fields#%E8%AF%AD%E6%B3%95
类型和值(Type and Value)
class 能够作为一个类型和一个值,但是最好 不要这么做
class Bag { }
const a: Bag = new Bag()
class C implements Bag { }
常用语法(common Syntax)
class User {
name: string // 必须声明才能在 constructor 赋值
constructor(name: string) {
this .name = name
}
}
以下是上面简写,public 可换成 private ,public readonly,protected, 等等......,但不能是 js 语法 static 和 # 修饰符
class User {
constructor(public name:string){}
}
?其它常用语法
interface Updatable { }
type Serializzable = {}
class Account { }
// 继承 Account 类,实现 Updatable 接口 和 Serializzable 类型
class User extends Account implements Updatable, Serializzable {
id: string;
displayName ?: boolean ; // 可选
name!: string; // 告诉类型检查器 name 有值
#attributes: Map<any, any>; // 私有属性,js语法
roles = ["user"]; // 默认值
readonly createdAt = new Date(); // 只读属性
constructor(id: string) {
super()
this .id = id
this .#attributes = new Map()
}
setName(name: string) { this .name = name } // 原型方法
verifyName = (name: string) => { this .name = name } // 实例方法
// 函数重载
sync(): Promise<{}>
sync(cb: (result: string) => void ): void
// 方法类型声明完成,后要接着方法实现
sync(cb?: (result: string)=> void ): void | Promise<{}> {}
// Getters and Setters
get accountID(){ return 123 }
set accountID(value: number){ /* * ... */ }
// protected 只能在类和继承类的后代类中使用,不可以在实例中使用
protected handleReques(){}
// 静态类型,js语法
static #userCount = 0 // 只能在静态方法里使用
static registerUser(user: number){ this .#userCount = user}
}
泛型(Generics)
class Box<Type> {
constructor(public content:Type){}
}
const stringBox = new Box("a package" )
// stringBox: Box<string>
?
抽象类(Abstract Classes)
在 TypeScript 中,类,方法和字段都可以是抽象的。抽象方法和字段都只能出现在抽象类中。
抽象类自身不能实例化,只能作为派生类的基类,派生类必须实现抽象类的所有抽象方法和字段。
abstract class Base {
abstract getName(): string;
printName() {
console.log( "Hello, " + this .getName());
}
}
const b = new Base(); // 错误,无法创建抽象类的实例。
class Derived extends Base {
// 必须实现该抽象函数
getName() {
return "world" ;
}
}
const d = new Derived();
d.printName();
抽象构造签名(Abstract Construct Signatures)
有时你想接受一个构造函数,产生一个实例,这个构造函数是某个 抽象类派生的类 。
Bad!这种写法,在传递抽象类的时候 TypeScript 没有报错,只有new 实例化才报错
function greet(ctor: typeof Base) {
const instance = new ctor(); // 无法创建抽象类的实例。
instance.printName();
}
greet(Base);
Great!接受一个带有构造签名的参数,这种写法,在传递抽象类的时候 TypeScript 就报错了
function greet2(ctor: new () => Base) {
const instance = new ctor();
instance.printName();
}
greet2(Derived);
greet2(Base);
抽象类继承抽象类
抽象类继承抽象类,两抽象类会进行合并,出现相同名称的抽象方法和字段,如果不同类型会报错,但是相同类型,子类型,any,这些都不会报错。
abstract class Base {
abstract getName(): string;
abstract asd: string
printName() {
console.log( "Hello, " + this .getName());
}
}
abstract class Bag extends Base {
abstract getName(): any; // 相同抽象方法,返回值改为any,不报错
abstract asd: '456' // 相同抽象字段,返回值改为 string 子类型,不报错
}
class Derived extends Bag {
constructor(public asd: '456' ) {
super()
}
getName() {
return 123 ;
}
}
const d = new Derived('456' );
d.printName();
这里的 extends 是js 语法,类只能继承一个。并不是 ts 的 extends, 用于 Interface? 扩展,和类型缩窄
class Derived extends Bag, Base {} // 错误
修饰器和属性(Decorators and Attributes)
在 "tsconfig" 中打开 "experimentalDecorators"
可以在类,方法,方法参数,属性和访问器上用修饰器
import { Syncable, triggerSync, preferCache, required } from "mylib"
@Syncable
class User {
@triggerSync() // 方法
save() { }
@preferCache( false ) // 访问器
get displayName() { }
update(@required info: Partial <User>) { } // 方法参数
}
一个声明应用多个装饰器,会 从 下到上调用
function first(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
console.log( "first(): called" );
};
function second(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
console.log( "second(): called" );
};
class ExampleClass {
// 单行,多行,两种写法
@first @second method() { }
// @first
// @second
// method() { }
}
const exampleClass = new ExampleClass();
exampleClass.method()
// second(): called
// first(): called
一个声明应用多个装饰器工厂(decorator factories),会 从上到下调用 后, 再 从下到上 调用 返回的函数
function first() {
console.log( "first(): factory evaluated" );
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
console.log( "first(): called" );
};
}
function second() {
console.log( "second(): factory evaluated" );
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
console.log( "second(): called" );
};
}
class ExampleClass {
@first()
@second()
method() { }
}
const exampleClass = new ExampleClass();
exampleClass.method()
// first(): factory evaluated
// second(): factory evaluated
// second(): called
// first(): called
Decorator Evaluation
应用于类内部各种声明的装饰器,有一个明确定义的顺序:
实例成员,(参数装饰器,其次是方法),(访问器),(属性装饰器), 这三者按照声明顺序调用 静态成员,(参数装饰器,其次是方法),(访问器),(属性装饰器), 这三者按照声明顺序调用 构造函数参数修饰器 类修饰器
?还有一个注意点,参数修饰器中,越往后的参数修饰器,越早调用
function classDecorator(constructor: Function) {
console.log( "classDecorator" );
};
function propertyDecorator(name: string) {
return function (target: any, propertyKey: string) {
console.log(name);
}
}
function parameterDecorator(name: string) {
return function (target: any, functionName: string, index: number) {
console.log(name);
}
}
function methodDecorator(name: string) {
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
console.log(name);
};
}
function accessorDecorator(name: string) {
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
console.log(name);
}
}
@classDecorator
class ExampleClass {
constructor(@parameterDecorator( "constructorParameter") greeting: string, @parameterDecorator("constructorParameter2" ) public appService: string) {
this .greeting = greeting
}
@accessorDecorator( "staticAccessor") static get x() { return 123 }
@propertyDecorator( "staticProperty" ) static id: number
@methodDecorator( "staticMethod" )
static smethod(@parameterDecorator( 'staticParmeter' ) value: string) { }
@propertyDecorator( "instanceProperty" ) greeting: string
@methodDecorator( "instanceMethod" )
method(value: string, @parameterDecorator( 'instanceParmeter' ) value2: string) { }
@accessorDecorator( "instanceAccessor") get x() { return 123 }
}
const exampleClass = new ExampleClass('asd', 'wew' );
exampleClass.method( 'a', 'b' )
// [LOG]: "instanceProperty"
// [LOG]: "instanceParmeter"
// [LOG]: "instanceMethod"
// [LOG]: "instanceAccessor"
// [LOG]: "staticAccessor"
// [LOG]: "staticProperty"
// [LOG]: "staticParmeter"
// [LOG]: "staticMethod"
// [LOG]: "constructorParameter2"
// [LOG]: "constructorParameter"
// [LOG]: "classDecorator"
?
感谢观看,欢迎互相讨论与指导,以下是参考资料链接?
https://HdhCmsTesttypescriptlang.org/static/TypeScript%20Classes-83cc6f8e42ba2002d5e2c04221fa78f9.png
?
查看更多关于TypeScript 之 Class的详细内容...