TS入门篇 | 详解 TypeScript 类类型(上)

简介: 传统的面向对象语言都是基于类的,而JavaScript是基于原型的。在ES6中拥有了class关键字,虽然它的本质依旧是构造函数,但是能够让开发者更舒服的使用class了。 TypeScript 作为 JavaScript 的超集,自然也是支持 class 全部特性的,并且还可以对类的属性、方法等进行静态类型检测。下面就来看看 TypeScript 中的类类型。

一、类的概念


1. 类的使用


在开发过程中,任何实体都可以被抽象为一个使用类表达的类似对象的数据结构,这个数据结构既包含属性,又包含方法。在TypeScript 中可以这样来抽象一个坐标点类:

class Point {
  x: number;
  y: number;
  constructor(x: number, y: number) {
    this.x = x;
    this.y = y;
  }
  getPosition() {
    return `(${this.x}, ${this.y})`;
  }
}
const point = new Point(1, 2);
point.getPosition()   // (1, 2)
复制代码


这里定义了一个 Point 坐标点类,它拥有两个number类型的属性 x 和 y,一个构造器函数和一个getPosition方法。后面通过new实例化了一个Point,并将实例赋值给变量point,最后通过实例调用了类中定义的 getPosition 方法。

在ES6之前,需要使用函数+原型链的形式进行模拟定义类:

function Point(x, y) {
  this.x = x;
  this.y = y;
}
Point.prototype.getPosition = function() {
  return `(${this.x}, ${this.y})`;
}
const point = new Point(1, 2);
point.getPosition()   // (1, 2)
复制代码


开始定义了 Point 类的构造函数,并在构造函数内部定义了 x 和 y 属性,后面通过 Point 的原型链添加了 getPosition 方法。这样也模拟实现了 class 的功能,但是看起来麻烦很多,并且缺少静态类型检测。因此,类是 TypeScript 编程中十分有用且不得不掌握的工具。


2. 类的继承


下面来看一下作为面向对象的三大也行之一的继承,在 TypeScript 中,可以使用 extends 关键字来定义类继承的抽象模式:

class A {
  name: string;
  age: number;
  constructor(name: string, age: number) {
      this.name = name;
      this.age = age;
  }
  getName() {
      return this.name;
  }
}
class B extends A {
  job: string;
  constructor(name: string, age: number) {
      super(name, age);
      this.job = "IT";
  }
  getJob() {
      return this.job;
  }
  getNameAndJob() {
      return super.getName() + this.job;
  }
}
var b = new B("Tom", 20);
console.log(b.name);
console.log(b.age);
console.log(b.getName());
console.log(b.getJob());
console.log(b.getNameAndJob());
//输出:Tom,20,Tom,IT,TomIT
复制代码


如上,B继承A,那A被称为父类(超类),B被称为子类(派生类)。这就是类最基本的继承用法,B就是一个派生类,它派生自A类,此时B的实例继承了基类A的属性和方法。因此,实例 b 支持 name、age、getName 等属性和方法。


需要注意,派生类如果包含一个构造函数constructor,则必须在构造函数中调用 super() 方法,这是 TypeScript 强制执行的一条重要规则。否则就会报错:Constructors for derived classes must contain a 'super' call.


那这个 super() 有作用呢?其实这里的 super 函数会调用基类的构造函数,当我们把鼠标放在super方法上面时,可以看到一个提示,它的类型是基类 A 的构造函数:constructorA(name: string,age: number): A。并且指明了需要传递两个参数,不然TypeScript就会报错。


二、类的修饰符


1. 访问修饰符


在 ES6 标准类的定义中,默认情况下,定义在实例的属性和方法会在创建实例后添加到实例上;而如果是定义在类里没有定义在 this 上的方法,实例可以继承这个方法;而如果使用 static 修饰符定义的属性和方法,是静态属性和静态方法,实例是没法访问和继承到的。


传统面向对象语言通常都有访问修饰符,可以通过修饰符来控制可访问性。TypeScript 中有三类访问修饰符:

  • public:修饰的是在任何地方可见、公有的属性或方法;
  • private:修饰的是仅在同一类中可见、私有的属性或方法;
  • protected:修饰的是仅在类自身及子类中可见、受保护的属性或方法。


(1)public

public表示公共的,用来指定在创建实例后可以通过实例访问的,也就是类定义的外部可以访问的属性和方法。默认是 public,但是 TSLint 可能会要求必须用限定符来表明这个属性或方法是什么类型的:


class Point {
  public x: number;
  public y: number;
  constructor(x: number, y: number) {
    this.x = x;
    this.y = y;
  }
  public getPosition() {
    return `(${this.x}, ${this.y})`;
  }
}
const point = new Point(1, 2)
console.log(point.x)   // 1
console.log(point.y)   // 2
console.log(point.getPosition())  // (1, 2)
复制代码


(2)private

private修饰符表示私有的,它修饰的属性在类的定义外面是没法访问的:


class Parent {
  private age: number;
  constructor(age: number) {
    this.age = age;
  }
}
const p = new Parent(18);
console.log(p);  // { age: 18 }
console.log(p.age); // error Property 'age' is private and only accessible within class 'Parent'.
console.log(Parent.age); // error Property 'age' does not exist on type 'typeof Parent'.
class Child extends Parent {
  constructor(age: number) {
    super(age);
    console.log(super.age); // Only public and protected methods of the base class are accessible via the 'super' keyword.
  }
}
复制代码


这里 age 属性使用 private 修饰符修饰,说明它是私有属性,打印创建的实例对象 p,发现它是有属性 age 的,但是当试图访问 p 的 age 属性时,编译器会报错,私有属性只能在类 Parent 中访问。


对于 super.age 的报错,在不同类型的方法里 super 作为对象代表着不同的含义,这里在 constructor 中访问 super,这的 super 相当于父类本身,使用 private 修饰的属性,在子类中是无法访问的。


(3) protected

protected是受保护修饰符,和private有些相似,但有一点不同,protected修饰的成员在继承该类的子类中可以访问。把上面那个例子父类 Parent 的 age 属性的修饰符 private 替换为


class Parent {
  protected age: number;
  constructor(age: number) {
    this.age = age;
  }
  protected getAge() {
    return this.age;
  }
}
const p = new Parent(18);
console.log(p.age); // error Property 'age' is protected and only accessible within class 'Parent' and its subclasses.
console.log(Parent.age); // error Property 'age' does not exist on type 'typeof Parent'.
class Child extends Parent {
  constructor(age: number) {
    super(age);
    console.log(super.age); // error Only public and protected methods of the base class are accessible via the 'super' keyword.
    console.log(super.getAge());
  }
}
new Child(18)
复制代码


protected还能用来修饰 constructor 构造函数,加了protected修饰符之后,这个类就不能再用来创建实例,只能被子类继承,ES6 的类需要用new.target来自行判断,而 TS 则只需用 protected 修饰符即可:


class Parent {
  protected constructor() {
    //
  }
}
const p = new Parent(); // error Constructor of class 'Parent' is protected and only accessible within the class declaration.
class Child extends Parent {
  constructor() {
    super();
  }
}
const c = new Child();
复制代码


相关文章
|
17天前
|
JavaScript 安全 前端开发
TypeScript类型声明:基础与进阶
通过本文的介绍,我们详细探讨了TypeScript的基础与进阶类型声明。从基本数据类型到复杂的泛型和高级类型,TypeScript提供了丰富的工具来确保代码的类型安全和可维护性。掌握这些类型声明能够帮助开发者编写更加健壮和高效的代码,提高开发效率和代码质量。希望本文能为您在使用TypeScript时提供实用的参考和指导。
30 2
|
1月前
|
JavaScript 开发者
在 Babel 插件中使用 TypeScript 类型
【10月更文挑战第23天】可以在 Babel 插件中更有效地使用 TypeScript 类型,提高插件的开发效率和质量,减少潜在的类型错误。同时,也有助于提升代码的可理解性和可维护性,使插件的功能更易于扩展和升级。
|
2月前
|
JavaScript 前端开发
TypeScript【类型别名、泛型】超简洁教程!再也不用看臭又长的TypeScript文档了!
【10月更文挑战第11天】TypeScript【类型别名、泛型】超简洁教程!再也不用看臭又长的TypeScript文档了!
|
2月前
|
JavaScript 前端开发
Vue2整合TypeScript:借助vue-property-decorator以类模式编写组件
Vue2整合TypeScript:借助vue-property-decorator以类模式编写组件
146 3
|
2月前
|
JavaScript 前端开发 安全
TypeScript【基础类型】超简洁教程!再也不用看臭又长的TypeScript文档了!
【10月更文挑战第9天】TypeScript【基础类型】超简洁教程!再也不用看臭又长的TypeScript文档了!
|
2月前
|
移动开发 JavaScript 前端开发
TypeScript:数组类型&函数使用&内置对象
本文介绍了 TypeScript 中的数组类型、对象数组、二维数组、函数、函数重载、内置对象等概念,并通过代码示例详细展示了它们的使用方法。还提供了一个使用 HTML5 Canvas 实现的下雨效果的小案例。
|
1月前
|
JavaScript 前端开发 安全
TypeScript进阶:类型系统与高级类型的应用
【10月更文挑战第25天】TypeScript作为JavaScript的超集,其类型系统是其核心特性之一。本文通过代码示例介绍了TypeScript的基本数据类型、联合类型、交叉类型、泛型和条件类型等高级类型的应用。这些特性不仅提高了代码的可读性和可维护性,还帮助开发者构建更健壮的应用程序。
27 0
|
2月前
|
JavaScript 索引
TypeScript(TS)安装指南与基础教程学习全攻略(二)
TypeScript(TS)安装指南与基础教程学习全攻略(二)
56 0
|
2月前
|
JavaScript 前端开发 安全
TypeScript(TS)安装指南与基础教程学习全攻略(一)
TypeScript(TS)安装指南与基础教程学习全攻略(一)
29 0
|
3月前
|
JavaScript
typeScript进阶(9)_type类型别名
本文介绍了TypeScript中类型别名的概念和用法。类型别名使用`type`关键字定义,可以为现有类型起一个新的名字,使代码更加清晰易懂。文章通过具体示例展示了如何定义类型别名以及如何在函数中使用类型别名。
44 1
typeScript进阶(9)_type类型别名