学习目标:
1. class 类
2. 类型兼容性
3. 交叉类型
4. 泛型 和 keyof
5. 索引签名类型 和 索引查询类型
6. 映射类型
//以下只说明了class类,需要其他的请跳转主页TypeScript
目录
class 类
class的基本使用
//class的基本使用
class Person{}
const p = new Person()
// 解释:
// 1. 根据 TS 中的类型推论,可以知道 Person 类的实例对象 p 的类型是 Person。
// 2. TS 中的 class,不仅提供了 class 的语法功能,也作为一种类型存在。
为class类添加属性(实例属性初始化)
// 实例属性初始化:
class Person2{
age: number
//ts中的类型推断会推断gender类型为string
gender = '女'
}
const p2 = new Person2();
console.log(p2.age);
console.log(p2.gender);//女
// 解释:
// 1. 声明成员 age,类型为 number(没有初始值)。
// 2. 声明成员 gender,并设置初始值,此时,可省略类型注解(TS 类型推论 为 string 类型)。
构造函数
// 构造函数:
class Person3{
age: number
gender: string
constructor(age: number, gender:string){
this.age = age;
this.gender = gender
}
}
const p3 = new Person3(20,'男');
console.log(p3.age,p3.gender);//20 男
// 解释:
// 1. 成员初始化(比如,age: number)后,才可以通过 this.age 来访问实例成员。
// 2. 需要为构造函数指定类型注解,否则会被隐式推断为 any;构造函数不需要返回值类型。
实例方法
// 实例方法:
class Point {
x = 10
y = 20
scale(num: number):void {
this.x *= num
this.y *= num
}
}
//new的是一个方法
const pi = new Point()
pi.scale(10)//放大10倍
console.log(pi.x,pi.y)//100 200
// 解释:方法的类型注解(参数和返回值)与函数用法相同
// 解释:方法的类型注解(参数和返回值)与函数用法相同
类的继承
extends(继承父类)
//父类
class Animal {
move(){
console.log(' 动物 ! ')
}
}
//子类
class Dog extends Animal {
name = '中华田园狗'
bark(){
console.log(' 狗叫 ! ')
}
}
const d = new Dog()
d.move(); // 动物 !
d.bark() // 狗叫 !
console.log(d.name) //中华田园狗
// 解释:
// 1. 通过 extends 关键字实现继承。
// 2. 子类 Dog 继承父类 Animal,则 Dog 的实例对象 dog 就同时具有了父类 Animal 和 子类 Dog 的所有属性和方法。
implements(实现接口)
interface Singable {
name : string
sing(): void
}
class Person4 implements Singable{
name = 'zys'
sing() {
console.log('敲代码不如唱歌 ')
}
}
const p4 = new Person4()
console.log(p4.name)//zys
p4.sing()//敲代码不如唱歌
// 解释:
// 1. 通过 implements 关键字让 class 实现接口。
// 2. Person 类实现接口 Singable 意味着,Person 类中必须提供 Singable 接口中指定的所有方法和属性。
例如:
如果Person 类中没有实现接口中的所有属性和方法则会报错
可见性修饰符
public
class Animal {
public move(){
console.log(' 公共类中的动物 ! ')
}
}
const Am = new Animal()
Am.move();//公共类中的动物
// 解释:
// 1. 在类属性或方法前面添加 public 关键字,来修饰该属性或方法是共有的。
// 2. 因为 public 是默认可见性,所以,可以直接省略。
protected
// protected(受保护的)
//父类
class Animal3 {
protected move(){
console.log(' 受保护的动物 ')
}
run() {
console.log('凑数的')
//同个类中掉用 move方法
this.move()
}
}
//子类
class Dog extends Animal3 {
bark(){
console.log(' 狗 ')
//子类中调用 move方法
this.move()
}
}
const dd = new Do();
dd.run() // 凑数的 受保护的动物
dd.bark() // 狗 受保护的动物
// 解释:
// 1. 在类属性或方法前面添加 protected 关键字,来修饰该属性或方法是受保护的。
// 2. 在子类的方法内部可以通过 this 来访问父类中受保护的成员,但是,对实例不可见!
例如:实例方法move会报错
private
// 私有的private
// 父类
class Fu {
// 私有的 这里的__run__ 命名类似于python 合法的
private __run__() {
console.log('Animal 内部辅助函数')
}
// 受保护的
protected move() {
this.__run__()
console.log('走两步')
}
// 公开的
public run() {
this.__run__()
this.move()
console.log('跑起来')
}
}
//实例化父类
const a = new Fu()
// a.__run__() //报错
// 子类
class Zi extends Fu {
bark() {
// this.__run__() //报错
console.log('旺旺!')
}
}
//实例化子类
const dg = new Zi()
// dg.__run__() //报错
实例对象
//实例化父类
//实例化子类
// 解释:
// 1. 在类属性或方法前面添加 private 关键字,来修饰该属性或方法是私有的。
// 2. 私有的属性或方法只在当前类中可见,对子类和实例对象也都是不可见的!
readonly
class Person5 {
//只读属性
// 注意:只要是 readonly 来修饰的属性,必须手动提供明确的类型
readonly age: number = 18
constructor(age: number) {
this.age = age;
}
//错误演示:
// readonly setAge(){
// this.age = age
// }
}
// 解释:
// 1. 使用 readonly 关键字修饰该属性是只读的,注意只能修饰属性不能修饰方法。
// 2. 注意:属性 age 后面的类型注解(比如,此处的 number)如果不加,则 age 的类型为 18 (字面量类型)。
class Person6 {
//错误演示:
readonly age = 18
//使用readonly 修饰属性时,如果这个属性有默认值,则一定要指定其类型
//否则会根据类型推断, 推断 age 为 18 这个类型,而不是number
constructor(age: number) {
//this.age = age; //报错
}
}
又如果 使用readonly(只读修饰符)为 age 时没有定义类型,又没定义默认值
此时的 age 为any类型
class Person7 {
//错误演示:
readonly age
//age 为any类型
}
// 3. 接口或者 {} 表示的对象类型,也可以使用 readonly。
接口
//接口
interface IPerson{
//readonly 只读不能修改
readonly name: string
}
let obj: IPerson = {
name: 'zys'
}
//错误示范:
// obj.name = 'rose'
//无法为“name”赋值,因为它是只读属性。
对象类型{}
//{} 表示的对象类型
let object: { readonly name: string} = {
name: 'jack'
}
//错误示范:
//无法为“name”赋值,因为它是只读属性。
// obj.name = 'rose'