TS高级类型
TS中的高级类型有很多 重点学习一下高级类型:
class类
类型兼容性
交叉类型
泛型和keyof
索引签名类型和索引查询类型
映射类型
class类
TS全面知识ES6中引入的class关键字 并为其添加了类型注解和其他语法(比如,可见性修饰符等)
class基本使用:
class Person{}
const p=new Person()
解释:
根据TS中的类型推论 可以知道Person类的实例对象p的类型是Person
TS中的class 不仅提供了class的语法功能 也作为一种类型存在
示例属性初始化:
class Person {
age:number
gender='男' //gender:string='男'
}
解释:
声明成员age 类型为number (没有初始值)
声明成员gender 并设置初始值 此时 可省略类型注解(TS类型推论为string类型)
class Person {
age:number
gender:string
constructor(age:number,gender:string){
this.age=age
this.gender=gender
}
}
解释:
成员初始化(比如 age:number)后,才可以通过this.age来访问实例成员
需要为构造函数指定类型注解,否则会被隐式推断为any,构造函数不需要返回值类型
class Point {
x=10
y=10
fn(n:number):void{
this.x*=n
this.y*=n
}
}
解释: 方法的类型注解(参数和返回值)与函数用法相同
类继承的两种方式:
extends(继承父类)
implements(实现接口)
说明:JS中只有extends 而iimplements是TS提供的
通过 extends(继承父类)
class Animal{
move(){console.log('i`m running')}
}
class Dog extends Animal{
bark(){console.log('wang~')}
}
const dog=new Dog()
解释:
通过extends关键字 实现继承
子类Dog继承父类Animal 则Dog的实例对象dog就同时具有父类Animal和子类Dog的属性和方法
通过 implements(实现接口)
interface Singable{
sing():void
}
class Person implements Singable{
sing(){
console.log('呦吼吼~~~~~')
}
}
解释:
通过implements关键字让class实现接口
Person类实现接口Singable意味着 Person类中必须提供Singable接口中指定的所有方法和属性
类成员可见性:可以使用TS来控制class的方法或属性对于class外的代码是否可见
可见性修饰符包括:public(公有的:默认就是公有 可以省略) protected(受保护的) private(私有的)
1.public:表示公有的 公开的 公有成员可以被任何地方访问 默认可见性
class Animal{
pubilc move(){
console.log('i`m running~~')
}
}
解释:
在类属性或方法前面添加public关键字 来叙事该属性或方法是共有的
因为public是默认可见性 所以 可以直接省略
2.protected: 表示受保护的 仅对期声明所在类和子类中(非实例对象)可见
class Animal{
protected move(){console.log('我就不动')}
public go(){this.move()}
}
class Dog extends Animal{
dogGo(){this.move()}
}
const dog=new Dog()
可以访问到:dog.go() dog.dogGo()
不可以访问: dog.move() //属性“move”受保护,只能在类“Animal”及其子类中访问。
解释:
在雷属性或方法前面添加 protected 关键字 来修饰该属性或方法是受保护的
在子类方法内部可以通过this来访问父类中受保护的成员 但是 对实例不可见!!!!!
3. private:表示私有的 只在当前类中可见 对实例对象以及子类也是不可见的
class Animal{
private move(){console.log('就不!!!')}
walk(){this.move()}
}
解释:
在类属性或方法面前添加private关键字 来修饰该属性或方法是私有的
私有的属性或方法 只在当前类中可见 对子类和实例对象也都是不可见的
除了可见性修饰符外,还有一个常见的修饰符就是:readonly(只读修饰符)
readonly:表示只读 用来方式在狗仔函数之外对属性进行赋值
<!!!!注意 只要是readonly 来修饰的属性,必须手动提供明确的类型>
class Person{
readonly age:number=18
constructor(age:number){
this.age=age
}
}
解释:
使用readonly关键字修饰该属性是只读的 注意只能修饰属性 不能修饰方法
注意:age后边的类型注解(比如number)如果不加 则age的类型为 18(字面量类型)
接口或者{}表示的对象类型 也可以使用readonly
const obj: { readonly name: string } = {
name: 'xiaohong'
}
交叉类型
交叉类型(&):功能类似于接口继承(extends) 用于组合多个类型为同一个类型(常用于对象类型).
interface Person {name:string}
interface Contact {phone:string}
type PersonDetail=Person&Contact
let obj:PersonDetail={
name:'rose',
phone:'13133111133'
}
解释: 使用交叉类型后 新的类型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
泛型
泛型是可以在保护类型安全前提下,让函数与多种类型一起工作 从而实现复用 常用于 函数 接口 calss 中
泛型在保证类型安全(不丢失类型信息)的同时,可以让函数等与多种不同的类型一起工作,灵活可复用
创建一个泛型函数:
function id<Type>(value:Type):Type {return value}
解释:
语法:在函数名称的后面 添加<>(尖括号) 尖括号中添加类型变量,比如此处的Type.
类型变量Type 是一种特殊类型的变量 他处理类型 而不是值
该类型变量相当于一个类型容器 能够捕获用户提供的类型(具体是什么类型由用户调用该函数时指定)
因为Type是类型 因此可以将其作为函数参数和返回值的类型,表示参数和返回值具有相同的类型
类型变量Type 可以是任意合法的变量名称
调用泛型函数:
function id<Type>(value:Type):Type{return value}
const num=id<number>(12) //const num:number
const str=id<string>("a") //const str:string
解释:
语法:在函数名称的后面 添加<> (尖括号) 尖括号中指定具体的类型 比如 此处的number
当传入类型number后 这个类型就会被函数声明时 指定的类型变量Type捕获到.
此时 Type的类型就是number 所以 函数id参数和返回值的类型也都是number
同样 如果传入string类型 函数id 参数和返回值的类型就都是string
这样 通过泛型就做到了 让id函数与多种不同的类型一起工作 实现了复用的同时 保证类类型安全