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://www.typescriptlang.org/static/TypeScript%20Classes-83cc6f8e42ba2002d5e2c04221fa78f9.png
查看更多关于TypeScript 之 Class的详细内容...