一、前言
各位读者 ,大家好,今天我来完成TypeScript的下篇了,上篇我们主要介绍了TypeScript的类型声明,接口等概念,如果读者朋友还没有了解过这部分的概念,请前往上一篇进行查看哦,今天我们将对TypeScript(以下简称TS)的类,泛型等概念做一个总结和介绍。话不多说我们接下来开始。。。
在开始之前,我希望各位能够准备几样知识储备,ES6中的类,面向对象对象编程思想。
二、认识类
类是面向对象编程思想中非常重要的概念,ES6对类进行了支持,既我们class 声明方式,在此之前我们只能使用构造函数去创建类,但今后我们可以使用更为直观的语法啦。
(1)类的继承:我们假设你已经懂得了如何使用类,知道类的概念了,以下的内容我们当做复习好么?
// 关于类
class People {
name:string
constructor(name:string){
this.name = name
}
say(){
console.log('人都有自己的语言,可以进行表达')
}
}
class Man extends People {
muscle:string
constructor(name,muscle:string){
super(name)
this.muscle = muscle
}
aggression(){
console.log('男性往往更加有侵略性,肌肉力量更加发达')
}
}
class Woman extends People {
careful:string
constructor (name:string,careful){
super(name)
this.careful = careful
}
baby(){
console.log('女性可以生孩子但是男性是不可以的,同时女性更加细腻')
}
}
// 以上的例子我们介绍了类的继承的特性,如果我们通过new关键字对Man new 出来的实例进行查看,它具有People的特性
let m1 = new Man('张三','他的肌肉很发达')
m1.name // 张三 继承自 People
m1.aggression() // 男性往往更加有侵略性,肌肉力量更加发达
小结:我们可以看到,类是可以进行继承,因此可以扩展很多动能,我们在react中进场可以看到这样的应用,创建类式组件时,都让其继承react.Component对么。
(2):类的几大修饰符,类中有很多可用的修饰符,可以帮助我们去对每一个属性进行约束定义和扩展。
// 下面来了解一下类的几大修饰符 public private protected static readonly
class Student {
static msg:string = '祖国的花朵' // 静态属性 属于这个类,而不属于实例对象,学生都是祖国的花朵
protected age:number // 被保护的属性 这个age可以在自己的类中和子类中进行使用,
private IdCardNum:number // 私有属性 这个身份证证,外界和子类都不能进行使用,更为的隐私
public name:string // 公有属性 如果不加任何修饰,任何属性其实都属于公有属性。
readonly sex:boolean // 只读属性 只能对其进行查看,而不能对其进行修改
constructor(name:string,age:number,sex:boolean,IdCardNum:number){
this.age = age
this.name = name
this.sex = sex
this.IdCardNum = IdCardNum
}
study(){
console.log(`${this.name}今年${this.age}岁,我每天都在好好的学习`)
}
}
class HightSchoolStudent extends Student {
constructor(name:string,age:number,sex:boolean,IdCardNum:number){
super(name,age,sex,IdCardNum)
}
test(){
console.log(this.age)
console.log(this.IdCardNum) // error 不能访问的
}
}
let s1 = new Student('张三',20,true,1111111)
s1.age // error 被保护属性不能在外部访问
// 存取器
class Person {
public name:string
public get fullName(){
return this.name
}
public set fullName(value : string) {
console.log('我被修改了')
this.name = value;
}
}
let p1 = new Person()
p1.fullName = '小鹏'
小结:各位读者一样要记得区分 protected 和 private 的区别哦,前者是可以在内部和子类中使用,但后者只能在内部使用, 后者相对于前者来说更加隐私,更为私密,如果记不住,就记得越短越私密好么。。。。其他的修饰符都很见名知意,我们不多加强调了哦。
三、泛型
我们要来介绍TS的重头戏啦,泛型,在认知让泛型之前我们来看看问题,今天我想定义一个函数接口
// 泛型的初体验
function fun0(arg:string):string {
return arg
}
这个接口相信你肯定可以看的懂,但是第二天,发现我们类型不对要换一下了
function fun1(arg:number):number{
return arg
}
然后又到了后天我们发现业务需求中又得换一下类型了
function fun1(arg:boolean):boolean{
return arg
}
各位发现了么,整个过程中,我们的业务需求仅仅是想换一下类型,但是函数结构都是没有变得,这种数据类型未知的情况,我们肯定会经常遇到,这个时候,我们会不会有一定思考呢,要是我们提前不用指定类型,而是使用时指定类型会不会更好呢。。。。
(1)因此泛型诞生了
// 问题:如果这个参数不是很固定怎么办,难道我们要一个一个写么当然不是我们可以指定一个类型
function fun2<T>(arg:T):T{ // 这个T类型在定义时是未知的在使用时才进行定义
return arg
}
使用时我们这样
fun2<string>('张三')
fun2<number>(111)
fun2<boolean>(false)
问题是不是就解决了,接下来我们同样的,大刀阔斧的做一下更加深入的例子
(2):创建泛型函数
let fun3:<T>(arg:T)=>T // 这便是一个表达式版的泛型函数了
// 根据上面的定义我们写出下面这样的函数类型
fun3 = function <Type>(arg:Type):Type{
return arg
}
(3):创建泛型类
// 泛型类
class MyfirstClass <Type> {
public store:Type[]
add(arg:Type){
this.store.push(arg)
}
minus(){
this.store.unshift()
}
}
(4):创建泛型接口
interface MyFirstInterface<Type>{
name:Type
add():Type
}
(5):泛型的继承
// 泛型继承
interface hasLength {
length:number
}
// 当我们想对某个未知类型做特定操作,但发现未知属性没有相应的操作条件,可以使用继承使其继承相应的属性,进行操作。
function doSelf <T extends hasLength>(arg:T):T{
console.log(arg.length)
return arg
}
(6):泛型的应用
// 小结:什么是泛型,所谓泛型,其实就是在进行定义函数 ,类,接口是,不预先指定类型,因为往往我们也不知道到将来用的时候到底使用什么样的类型,
// 但是又不能直接使用any来代替,因为这样就失去的ts的意义了,此时我们可以对该未知的类型进行一个泛型定义,等将来用的时候我们再进行定义,这便是泛型
// 函数使用泛型
function createArr<T>(value:T,count:number):Array<T>{
let arr:Array<T> = []
for(var i:number=0;i<count;i++){
arr.push(value)
}
return arr
}
// 使用时
let name:string = '小鹏'
let arr0 = createArr<string>(name,10)
let arr1 = createArr<number>(10,10)
console.log(arr0)
// 接口定义泛型
interface Store <T> {
store:Array<T> // 仓库
add:(thing:T)=>Array<T>
sell:(name:string)=>Array<T>
}
class Pet {
name:string = ''
price:number = 999
constructor(name:string,price:number){
this.name = name
this.price = price
}
say(){
alert('主人,你好')
}
}
class PetStore implements Store<Pet>{
store:Array<Pet> = []
add(thing:Pet){
this.store.push(thing)
return this.store
}
sell(name:string){
let index:number
for(var i:number=0;i<this.store.length;i++){
if(this.store[i].name == name){
index = i
}
}
this.store.splice(index,1)
return this.store
}
}
let ps = new PetStore()
let p1 = new Pet('小张',22)
ps.add(p1)
console.log(ps)
四、结语
最后感谢你能够将这片文章看完,虽然这片文章是下篇,但其实TS的学习其实远没有结束,本篇文章只是对TS的最浅层次的使用做了一定的总结,其实还有更为有趣和惊艳的写法呢,下一篇我争取写一篇关于TS的进阶的一些用法和跟大家一起交流一部分关于TS高阶部分的应用,拭目以待吧,这篇文章当然还有很多需要改进的地方,如果读者发现了希望大佬能够在评论区指正哦,我一定第一时间改善,还是那句话,立志成为一名优秀的前端工程师,我们一直在路上,一起加油。