TS中的高级类型有很多,重点学习以下高级类型:
TypeScript全面支持ES2015引入的class关键字,并为其添加了类型注解和其他语法(eg:可见性修饰符等)
class的基本使用:
解释:
实例属性初始化:
// 实例属性初始化
class Person{
age: number
gender = '男' // (property) Person.gender: string
// gender:string = '男'
}
const p = new Person()
p.age
p.gender
解释:
构造函数:
class Person {
age: number
gender: string
constructor(age: number, gender: string) {
this.age = age
this.gender = gender
}
}
const p = new Person(18, '男')
console.log(p.age,p.gender)// 18 男
解释:
class Point {
x = 10
y = 20
scale(n: number):void {
this.x *= n
this.y *= n
}
}
const p = new Point()
p.scale(10)
console.log(p.x,p.y)// 100 200
解释:方法的类型注解(参数和返回值)与函数用法相同。
类继承的两种方式:
说明:JS中只有extends,而implements是TS提供的。
1)extends继承
// extends继承
class Animal {
move() {
console.log('Moving along')
}
}
class Dog extends Animal {
bark() {
console.log('汪汪')
}
}
const dog = new Dog()
dog.move()// Moving along
dog.bark()// 汪汪
解释:
2)implements继承
// implements继承
interface Singable {
sing(): void
name : string
}
class Person implements Singable {
name = 'zs'
sing(){
console.log('小苹果')
}
}
const p = new Person()
p.sing()
解释:
类成员可见性:可以使用TS来控制class的方法或属性对于class外的代码是否可见。
可见性修饰符包括:
1)public :表示公有的、公开的,公有成员可以被任何地方访问,默认可见性。
// public
class Animal {
protected move() {
console.log('Moving along')
}
}
const a = new Animal()
a.move()
class Dog extends Animal{
bark() {
console.log('汪汪')
}
}
const d = new Dog()
d.bark()
d.move()
解释:
2)protected 表示受保护的,仅对其声明所在类和子类中(非实例对象)可见。
解释:
3)private 表示私有的,只在当前类中可见,对实例对象以及子类也是不可见的。
解释:
除了可见性修饰符之外,还有一个常见修饰符就是:readonly(只读修饰符)。
readonly:表示只读,用来防止在构造函数之外对属性进行赋值。
解释:
两种类型系统:
TS采用的是结构化类型系统,也叫做duck typing(鸭子类型),类型检查关注的是值所具有的形状。
也就是说,在结构类型系统中,如果两个对象具有相同的形状,则认为它们属于同一类型。
class Point {
x: number
y: number
}
class Point2D {
x: number
y: number
}
const p: Point = new Point2D()
解释:
注意:在结构化类型系统中,如果两个对象具有相同的形状,则认为它们属于同一类型,这种说法并不准确。
更准确的说法:对于对象类型来说,y的成员至少与x相同,则x兼容y(成员多的可以赋值给少的)
class Point {
x: number
y: number
}
class Point3D {
x: number
y: number
z: number
}
const p: Point = new Point3D()
p.x
p.y
p.z // 报错,无法访问,p不存在该属性//类型“Point”上不存在属性“z”
解释:
除了class外,TS中其他类型也存在相互兼容的情况,包括:
接口之间的兼容性,类似于class。并且,class和interface之间也可以兼容。
interface Point {
x: number
y: number
}
interface Point2D {
x: number
y: number
}
interface Point3D {
x: number
y: number
z: number
}
let p1: Point
let p2: Point2D = { x: 4, y: 5 }
let p3: Point3D = { x: 6, y: 7, z: 8 }
p1 = p2
p2 = p3
// 错误
// p3 = p1 //类型 "Point" 中缺少属性 "z",但类型 "Point3D" 中需要该属性。
// 类与接口之间也是兼容的
interface Point {
x: number
y: number
}
interface Point2D {
x: number
y: number
}
class Point3D{
x: number
y: number
z: number
}
let p1: Point
let p2: Point2D = { x: 4, y: 5 }
let p3: Point2D = new Point3D()
p2 = p3
p2 = new Point3D()
函数之间兼容性比较复杂,需要考虑:
1)参数个数,参数多的兼容参数少的(或者说,参数少的可以赋值给多的)
// 参数个数:少的赋值给多的(多的兼容少的)
type F1 = (a: number) => void
type F2 = (a: number, b: number) => void
let f1: F1 = (a)=>{}
let f2: F2 = f1 // 需要给f1初始值,不然报错:在赋值前使用了变量“f1”。
解释:
2)参数类型,相同位置的参数类型要相同(原始类型)或兼容(对象类型)
type F1 = (a: number) => void
type F2 = (a: number) => void
let f1: F1 = (a) => { }
let f2: F2 = f1
解释:函数类型F2兼容函数类型F1,因为F1和F2的第一个参数类型相同。
解释:
3)返回值类型,只关注返回值类型本身即可:
// 返回值类型
type F5 = () => string
type F6 = () => string
let f5: F5 = () => { return ''}
let f6: F6 = f5
type F7 = () => { name: string }
type F8 = () => { name: string; age: number }
let f7: F7
let f8: F8 = () => {
return {
name: 'zs',
age: 18
}
}
f7 = f8
解释:
交叉类型(&):功能类似于接口继承(extends),用于组合多个类型为一个类型(常用于对象类型)。
interface Person {
name: string
}
interface Contact {
phone: string
}
type PersonDetail = Person & Contact
let obj: PersonDetail = {
name: 'zs',
phone: '1333'
}
解释:使用交叉类型后,新的类型PersonDetail就同时具备了Person和Contact的所有属性类型。
相当于:
type PersonDetail {name: string;phone: string}
交叉类型(&)和接口继承(extends)的对比:
// 接口继承
interface A {
fn: (value: number) => string
}
interface B extends A{
fn: (value: string) => string
}
// 交叉类型
interface A {
fn: (value: number) => string
}
interface B {
fn: (value: string) => string
}
type C = A & B// fn: (value: string | number) => string
说明:以上代码,接口继承会报错(类型不兼容);
交叉类型没有错误,可以简单理解为:fn: (value: string | number) => string
1)泛型的基本使用
泛型是可以在保证类型安全前提下,让函数等与多种类型一起工作,从而实现复用,常用于:函数、接口、class中。
需求:创建一个id函数,传入什么数据就返回该数据本身(也就是说,参数和返回值类型相同)。
2)
(六)索引签名类型 和 索引查询类型
(七)映射类型