6.25、枚举的特点及原理
枚举是TS为数不多的非JavaScript类型及扩展(不仅仅是类型)的特性之一。
因为:其他类型仅仅被当做类型,而枚举不仅用作类型,还提供值(枚举成员都是有值的)。
也就是说,其他的类型会在编译为js代码时自动移除。但是,枚举型会编译为js代码。
说明,枚举与前面讲到的字面量类型+联合类型组合的功能类似,都用来表示一组明确的可选值列表。
一般情况下,推荐使用字面量类型+联合类型组合的方式,因为相比枚举,这种方式更加直观、简洁、高效。
6.26、any类型
原则:不推荐any!这会让TypeScript变为AnyScript,这样失去TypeScript类型的优势。
因为当值类型为any时,可以对该值进行任意操作,并且不会有代码提示。
let obj: any = { x: 0}
obj.bar = 100
obj()
const n: number = obj
解释:以上操作都不会有任何类型提示,即使可能存在错误!
尽可能 的避免使用any类型,除非临时使用any来”避免“书写很长、很复杂的类型!
其他隐式具有any类型的情况:1声明变量不提供类型也不提供默认值;2函数参数不加类型。
注意:因为不推荐使用any,所以,这两种情况下都应该提供类型!
6.27、TS中的typeof运算符
我们知道,js中提供了typeof操作符,用来在js中获取数据的类型。
console.log(typeof "hello world")
实际上,TS也提供了typeof操作符,可以在类型上下文中引用变量或属性的类型(类型查询)。
使用场景:根据已有变量的值,获取该值的类型,来简化类型的书写。
let p = { x:1, y:2 }
function formatPoint(point: {x: number; y: number}){}
formatPoint(p)
function formatPoint(point: typeof p)
解释:
1、使用 typeof 操作符来获取变量p的类型,结果与第一种(对象字面量形式的类型)相同。
2、typeof 出现在类型注解的位置(参数名称的冒号后面)做处的环境就在类型上下文(区别于js代码)
3、注意:typeof 只能用来查询变量或属性的类型,无法查询其他形式的类型,比如,函数调用的类型。
6.28、TS高级类型概述
TS中高级类型有很多,重点学习以下高级类型:
class类型
类型兼容性
交叉类型
泛型 和 keyof
索引签名类型 和 索引查询类型
映射类型
6.29、class的基本使用
TypeScript全面支持ES2015中引入class关键字,并为其添加了类型注解和其他语法(比如,可以见修饰符)
class基本使用:
class Person{}
const p: Person
const p = new Person()
解释:
1、根据TS中的类型推论,可以知道Person类的实例对象p的类型是Person
2、TS中的class 不仅提供了class的语法功能,也作为一种类型的存在。
6.30、class的构造函数
class Persion { age: number gender: string constructor(age: number, gender: string) { this.age = age this.gender = gender } }
解释:
1、成员初始化(比如,age: number)后,才可以通过this.age来访问实例成员。
2、需要为构造函数指定类型注解,否则会被隐式推断为any;构造函数不需要返回值类型。
6.31、class的实例方法
class Point { x = 10 y = 10 scale(n: nunber): void{ this.x += n this.y += n } }
解释:方法的类型注解(参数和返回值)与函数用法相同。
6.32、class继承(extends)
继承类的两种方式:
1、extends(继承父类);2、implements(实现接口)
说明:js中只有extends,而implements是TS提供的。
class Animal { move() { console.log('moving') } } class Dog extends Animal { bark() { console.log('汪汪汪!') } } const dog = new Dog()
解释:
1、通过extends关键字实现继承。
2、子类Dog继承父类Animal,则Dog的实例对象dog就同时具有了父类Animal和子类Dog的所有方法。
6.33、class继承(implements)
继承类的两种方式:
1、extends(继承父类);2、implements(实现接口)
interface Singable { sing(): void } class Person implements Singable { sing () { console.log('我是snow') } }
解释:
1、通过implements关键字让class实现接口。
2、Person类实现接口Singable意味着,Person类中必须提供Singable接口中指定的所有方法和属性。
6.34、class类的可见性修饰符(3-1 public)
类成员可见性:可以使用TS来控制class的方法或属性对于class外的代码是否可见。
可见性修饰符包括:1,public(公有的);2,protected(受保护的);3,private(私有的)
public:表示共有的、公开的,公有成员可以被任务地方访问,默认可见性。
class Animal {
public move() {
console.log('moving')
}
}
解释:
1、在类属性或方法前面添加public关键字,来修饰该属性或方法是共有的。
2、因为public是默认可见性,所以,可以直接省略。
14-class类的可见性修饰符(1public)_哔哩哔哩_bilibili
6.35、class类的可见性修饰符(3-2 protected)
protected:表示受保护,仅对其声明所在类和子类中(非实例对象)可见。
class Animal {
protected move (){
console.log('moving')
}
}
class Dog extends Animal {
bark() {
console.log('汪汪汪!')
this.move()
}
}
解释:
1、在类属性或方法前面添加protected关键字,来修饰该属性或方法是受保护的。
2、在子类的方法内部可以通过this来访问父类中受保护的成员,但是,对实例不可见!
6.36、class类的可见性修饰符(3-3 private)
private:表示私有的,只在当前类中可见,对实例对象以及子类也是不可见的。
class Animal {
private move () {
console.log('moving')
}
walk() {
this.move()
}
}
解释:
1、在类属性或方法前面添加private关键字,来修饰该属性或方法是私有的。
2、私有的属性或方法只在当前类中可见,对子类和实例对象也都是不可见的!
6.37、readonly只读修饰符
除了可见性修饰符之外,还有一个常见修饰符就是:readonly(只读性修饰符)。
readonly:表示只读,用来防止在构造函数之外对属性进行赋值。
class Person {
readonly age: number = 18
constructor(age: number) {
this.age = age
}
}
解释:
1、使用readonly关键字修饰该属性只读的,注意只能修改属性,不能修饰方法。
2、注意:属性age后面的类型注解(比如,此处的number)如果不加,则age的类型为18(字面量类型)
3、接口或者{}表示的对象类型,也可以使用readonly。
6.38、类型兼容性的说明
类中类型系统:1、StructuralType System(结构化类型系统)2、Nominal Type System(表明类型系统)。
TS采用的是结构化类型系统,也叫做duck typing(鸭子类型),类型检查关注的是值所具有的形式。
也就是说,在结构类型系统中,如果两个对象具有相同的形状,则认为他们属于同一类型。
class Point {x: number; y: number}
class Point2D {x: number; y: number}
const p: Point = new Point2D()
解释:
1、Point 和 Point2D是两个名称不同的类。
2、变量p的类型被显示标注为Point类型,但是,它的值却是Point2D的实例,并且没有类型错误。
3、因为TS是结构化类型系统,只检查Point和Point2D的结构是否相同(相同,都具有x和y两个属性,属性类型也相同)
4、但是,如果在Nominal Type System中(比如,c#、Java等),他们是不同的类,类型无法兼容。
6.39、对象之间的类型兼容性
注意:在结构化类型系统中,如果两个对象具有相同的形状,则认为他们属于同一类型,这种说法并不准确。更准确的说法:对于对象类型来说,y的成员至少与x相同,则x兼容y(成员多的可以赋值给少的)。
class Point {x: number; y: number}
class Point3D {x: number; y: number;z: number}
const p: Point = new Point3D()
解释:
1、Point3D的成员至少与Point相同,则Point兼容Point3D。
2、所以,成员多的Point3D可以赋值给成员少的Point。
6.40、接口之间的类型兼容性
6.41、函数之间的类型兼容性(3-1,函数参数)
6.42、函数之间的类型兼容性(3-2,函数参数)