为何不得不开始学习TypeScript中的class?

2026-05-27 16:581阅读0评论SEO基础
  • 内容介绍
  • 相关推荐

本文共计1418个文字,预计阅读时间需要6分钟。

为何不得不开始学习TypeScript中的class?

TypeScript 的 `class` 与 ES6 的 `Class` 类似,基本用法相近,主要差别在于 TypeScript 提供了更多的特性,如类型注解、继承、私有成员等。以下是两者的简要对比:

- 相似之处: - 都是用于定义对象的类型和行为的蓝图。 - 都支持构造函数、方法、属性等。

- 主要差别: - 类型注解:TypeScript 的 `class` 支持类型注解,可以更明确地指定成员的类型。 - 继承:TypeScript 的 `class` 支持继承(通过 `extends` 关键字),可以创建子类并继承父类的属性和方法。 - 私有成员:TypeScript 的 `class` 支持私有成员(通过 `private` 关键字),只能在类内部访问。 - 只读成员:TypeScript 的 `class` 支持只读成员(通过 `readonly` 关键字),一旦赋值,就不能修改。

例如,我们可以定义一个简单的 `Person` 类:

typescriptclass Person { private name: string; private age: number;

constructor(name: string, age: number) { this.name=name; this.age=age; }

为何不得不开始学习TypeScript中的class?

public getName(): string { return this.name; }

public getAge(): number { return this.age; }}

这样,我们就定义了一个具有类型注解、私有成员和继承等特性的 TypeScript 类。

TS 的 class 看起来和 ES6 的 Class 有点像,基本上差别不大,除了 可以继承(实现)接口、私有成员、只读等之外。

参考:typescript.bootcss.com/classes.html

基本用法

我们可以定义一个 class,设置几个属性,然后设置一个方法,封装 Object.assign 简化reactive 的赋值操作。

  • 创建自己的对象基类

import type { InjectionKey } from 'vue' class BaseObject { $id: string | symbol | InjectionKey<string> name: string age: number constructor (id: string, name: string, age: number) { this.$id = id this.name = name this.age = age } set $state(value: any) { Object.assign(this, value) } }

  • 使用

import { reactive, defineComponent } from 'vue' const _state = new BaseObject('007', 'jyk') const state = reactive(_state) state.$state = { name: '直接赋值' }

看着是不是眼熟?你猜对了!这里参考 Pinia 设置 $state ,实现给 reactive 直接赋值的功能。

reactive 哪都好,只是整体赋值的时候有点郁闷,这里简单封装了一下,实现直接赋值的功能。

类的继承

上面的方法只是封装了对象,那么数组怎么办呢?这里就需要用到“继承” extends 的用法。

  • 继承 js 的 Array 创建自己的数组类

class BaseArray extends Array { $id: string | symbol | InjectionKey<string> constructor () { // 调用父类的 constructor() super() this.$id = 'array' } set $state(value: any) { this.length = 0 if (Array.isArray(value)) { this.push(...value) } else { this.push(value) } } }

  • 使用

const _state2 = new BaseArray() const state2 = reactive(_state2) state2.$state = [ { name: '008' }, { name: '009' } ]

这样数组形式的 reactive ,也可以直接赋值了,是不是方便很多?

继承的是原生数组,所以拥有了数组的所有功能。
另外,子类的constructor里面,需要调用 super() 才会有 this。

实现接口

观察上面的两个 class,会发现拥有相同的成员:$id 和 $state。那么要不要约束一下?

如果想要实现约束功能的话,可以定义一个 interface 来实现。

  • 定义接口

interface IState { $id: string | symbol | InjectionKey<string> set $state(value: any) }

  • 实现接口

class BaseObject implements IState { 略 } class BaseArray extends Array implements IState { 略 }

这样设置之后,类的成员就要复合接口的定义,不符合的话会出现提示。

私有成员、只读成员

虽然可以使用 private、readonly 标识私有成员和只读成员,只是嘛,到目前为止有点鸡肋。因为只是在 TS 的范畴内给出错误提示,但是完全不影响运行。

那么能不能变相实现一下呢?可以的,只是有点绕圈圈,另外似乎不太正规。

我们把 $id 改为只读、伪隐藏成员。

  • 修改一下接口,使用访问器(get)设置 $id

interface IState { get $id(): string | symbol | InjectionKey<string> set $state(value: any) }

  • 修改一下对象基类,使用 get 访问器

class BaseObject implements IState { get $id(): string | symbol | InjectionKey<string> 略 }

  • 创建对象实例的函数

function createState(id: string, name: string, age: number) { // 继承 BaseObject 再定义一个class class myState extends BaseObject { constructor (name: string, age: number) { // 调用父类的 constructor() super(name, age) } // 使用 override 覆盖父类 $id override get $id() { return id } } const _state = new myState(name, age) const state = reactive(_state) return state }

  • 使用

const state3 = createState('010', 'jyk0013', 29) console.log(state3) console.log('state3 - keys', Object.keys(state3)) for (const key in state3) { console.log(key, state3[key]) }

  • 效果

  • 分析

把 $id 改为 get 访问器的方式,可以实现 readonly 的效果。

$id 放在 class (myState) 的“原型”上面,可以避免被遍历出来,这样就实现了伪隐藏的效果。

当然 使用 state.$id 的方式还是可以访问到的,所以是伪隐藏。

完整项目代码

gitee.com/naturefw-code/nf-rollup-state

本文共计1418个文字,预计阅读时间需要6分钟。

为何不得不开始学习TypeScript中的class?

TypeScript 的 `class` 与 ES6 的 `Class` 类似,基本用法相近,主要差别在于 TypeScript 提供了更多的特性,如类型注解、继承、私有成员等。以下是两者的简要对比:

- 相似之处: - 都是用于定义对象的类型和行为的蓝图。 - 都支持构造函数、方法、属性等。

- 主要差别: - 类型注解:TypeScript 的 `class` 支持类型注解,可以更明确地指定成员的类型。 - 继承:TypeScript 的 `class` 支持继承(通过 `extends` 关键字),可以创建子类并继承父类的属性和方法。 - 私有成员:TypeScript 的 `class` 支持私有成员(通过 `private` 关键字),只能在类内部访问。 - 只读成员:TypeScript 的 `class` 支持只读成员(通过 `readonly` 关键字),一旦赋值,就不能修改。

例如,我们可以定义一个简单的 `Person` 类:

typescriptclass Person { private name: string; private age: number;

constructor(name: string, age: number) { this.name=name; this.age=age; }

为何不得不开始学习TypeScript中的class?

public getName(): string { return this.name; }

public getAge(): number { return this.age; }}

这样,我们就定义了一个具有类型注解、私有成员和继承等特性的 TypeScript 类。

TS 的 class 看起来和 ES6 的 Class 有点像,基本上差别不大,除了 可以继承(实现)接口、私有成员、只读等之外。

参考:typescript.bootcss.com/classes.html

基本用法

我们可以定义一个 class,设置几个属性,然后设置一个方法,封装 Object.assign 简化reactive 的赋值操作。

  • 创建自己的对象基类

import type { InjectionKey } from 'vue' class BaseObject { $id: string | symbol | InjectionKey<string> name: string age: number constructor (id: string, name: string, age: number) { this.$id = id this.name = name this.age = age } set $state(value: any) { Object.assign(this, value) } }

  • 使用

import { reactive, defineComponent } from 'vue' const _state = new BaseObject('007', 'jyk') const state = reactive(_state) state.$state = { name: '直接赋值' }

看着是不是眼熟?你猜对了!这里参考 Pinia 设置 $state ,实现给 reactive 直接赋值的功能。

reactive 哪都好,只是整体赋值的时候有点郁闷,这里简单封装了一下,实现直接赋值的功能。

类的继承

上面的方法只是封装了对象,那么数组怎么办呢?这里就需要用到“继承” extends 的用法。

  • 继承 js 的 Array 创建自己的数组类

class BaseArray extends Array { $id: string | symbol | InjectionKey<string> constructor () { // 调用父类的 constructor() super() this.$id = 'array' } set $state(value: any) { this.length = 0 if (Array.isArray(value)) { this.push(...value) } else { this.push(value) } } }

  • 使用

const _state2 = new BaseArray() const state2 = reactive(_state2) state2.$state = [ { name: '008' }, { name: '009' } ]

这样数组形式的 reactive ,也可以直接赋值了,是不是方便很多?

继承的是原生数组,所以拥有了数组的所有功能。
另外,子类的constructor里面,需要调用 super() 才会有 this。

实现接口

观察上面的两个 class,会发现拥有相同的成员:$id 和 $state。那么要不要约束一下?

如果想要实现约束功能的话,可以定义一个 interface 来实现。

  • 定义接口

interface IState { $id: string | symbol | InjectionKey<string> set $state(value: any) }

  • 实现接口

class BaseObject implements IState { 略 } class BaseArray extends Array implements IState { 略 }

这样设置之后,类的成员就要复合接口的定义,不符合的话会出现提示。

私有成员、只读成员

虽然可以使用 private、readonly 标识私有成员和只读成员,只是嘛,到目前为止有点鸡肋。因为只是在 TS 的范畴内给出错误提示,但是完全不影响运行。

那么能不能变相实现一下呢?可以的,只是有点绕圈圈,另外似乎不太正规。

我们把 $id 改为只读、伪隐藏成员。

  • 修改一下接口,使用访问器(get)设置 $id

interface IState { get $id(): string | symbol | InjectionKey<string> set $state(value: any) }

  • 修改一下对象基类,使用 get 访问器

class BaseObject implements IState { get $id(): string | symbol | InjectionKey<string> 略 }

  • 创建对象实例的函数

function createState(id: string, name: string, age: number) { // 继承 BaseObject 再定义一个class class myState extends BaseObject { constructor (name: string, age: number) { // 调用父类的 constructor() super(name, age) } // 使用 override 覆盖父类 $id override get $id() { return id } } const _state = new myState(name, age) const state = reactive(_state) return state }

  • 使用

const state3 = createState('010', 'jyk0013', 29) console.log(state3) console.log('state3 - keys', Object.keys(state3)) for (const key in state3) { console.log(key, state3[key]) }

  • 效果

  • 分析

把 $id 改为 get 访问器的方式,可以实现 readonly 的效果。

$id 放在 class (myState) 的“原型”上面,可以避免被遍历出来,这样就实现了伪隐藏的效果。

当然 使用 state.$id 的方式还是可以访问到的,所以是伪隐藏。

完整项目代码

gitee.com/naturefw-code/nf-rollup-state