Bootstrap

小白必看的入门级TS学习教程


一、Ts中的数据类型

在介绍数据类型前,先说明一下ts中的声明、赋值方式。
1)先声明 需要时再赋值:

let c:number;
c=5

2)声明后直接赋

let c:boolean = true;

3)直接赋值后该变量类型默认为首次赋值时的类型不可再变

  let c=5//等价于let c:number=5;

1、number型

双精度 64 位浮点值。它可以用来表示整数和分数。

2、boolean 布尔型。

表示逻辑值:true 和 false。

3、string字符串型

一个字符系列,使用单引号(')或双引号(")来表示字符串类型。反引号(`)来定义多行文本和内嵌表达式。

4、数组类型:

声明变量为数组。

let arr: number[] = [1, 2];
let arr: Array<number> = [1, 2];
let arr: (number | string | number[] )[] = [1, '4', [1, 2, 4]]

5、元组类型

已知元素数量和类型的数组,各元素的类型不必相同,对应位置的类型需要相同。

   let x: [string, number]=['hello',1]

6、枚举类型:定义数值集合。

   enum Color{Red,Green}
   let i:Color=Color.Red

7、any 任意类型

声明为 any 的变量可以赋予任意类型的值,相当于关闭了类型检查

   显式:let a:any;
   隐式: let a;

8、unknown 未知类型

它和any的区别就是 当用any类型变量赋值其他值时其他值也变为any而unknown不可赋值给其他值,必须要赋值前需进行类型检查

let a:unknown;
let b:string;
if(typeof a ==='string')
{
    b=a
}

9、null:已定义且值为空

10、undefined:未定义的值

11、never 从不会出现的值

它只能被never类型的值赋值。
函数返回值设为它,则可以抛出异常或无法执行到终止点(例如无限循环)

function fn():never{
    throw new Error('空的')
}

12、void:表示为空,空也是存在的,这就是和never的区别。

13、object:键值对的形式。

①可同js直接声明

let Obj={
    a:'111'
}

②先以对象格式说明对象的属性、类型:

let obj={
    a:sting
}
obj={
    a:'abc'
}

要注意的是,若先说明了对象的属性及其类型,
则在创建这个对象时必须严格按照声明表示的属性类型
③类型声明限制对象结构,和②相似,只是写法略有不同。

type myType= { 
        firstName:string, 
        lastName:string, 
           sayHi(): string 
        } 
let obj:myType={
        firstName:'string', 
        lastName:'string', 
        sayHi():string{
            return 'ss'
         } 
}  

④接口类型限制对象结构

interface myInterface= { 
    firstName:string, 
    lastName:string, 
       sayHi(): string 
    } 
let obj:interface={
    firstName:'string', 
    lastName:'string', 
    sayHi():string{
        return 'ss'
     } 
 }               

③含有不确定是否存在的属性时,可在属性后加?,Eg:

let c:{
    name: boolean,
    age?: number
}

④属性个数不确定时

  let c:{
            [propName:string] : any
        }

14、函数:

基本语法:限制函数的返回值类型以及参数类型

function fn(a:number,b:number): void{
}

各种参数下的语法:
①参数类型确定但个数不确定时使用剩余参数语法即可:

 function fn(a:number[]){ } 这时的参数是作为数组传入

②有限个参数无法确定是否会存在:

 function fn(a:number,b?:string){ } 在该参数前加?修饰符即可 

③定义函数不确定参数类型/返回值类型,但确定个数

function fn<T>(a:T):T{return a } 

该函数意义为传入参数a,返回a,其中的就是在指明泛型名为T,该函数声明好后可直接调用,不声明泛型实际值,ts会自动判断,但不严谨最好指定。

不指定调用:fn(5) / 指定调用fn<number>(55)

也可以同时指定多个泛型,Eg:

   function fn<T,K>(a:T,b:K):T|K{}

该函数的返回值用了 | 表示返回值类型可以为T或K
函数重载:
1. 同名函数的参数的个数、类型或者顺序必须不同(其中有一个不一样就满足条件了) 叫函数的重载
2.重载允许一个函数接受不同数量或类型的参数时,作出不同的处理。 为同一个函数提供多个函数类型定义来进行函数重载
在定义重载的时候,一定要把最精确的定义放在最前面。因为查找重载列表,会从第一个重载定义开始使用,如果匹配成功的话就使用,否则就继续向下查下;最后函数实现时,需要使用 |操作符或者?操作符,把所有可能的输入类型全部包含进去(不确实的话可以写any)
3. 函数重载的意义在于能够让你知道传入不同的类型参数得到不同的类型结果,如果传入的参数不同,但是得到的结果(类型)却相同,那么这里就不需要使用函数重载

15、零散知识点

1.值可以用|表示:let a:1|2; 基本类型有意义
2. 值可以用&表示:let a:{name:string} &{age:number} 用于对象
3. 可以为类型取别名:

type myType=1|2|3;
   let a:myType;

4.类型断言:允许变量从一种类型更改为另一种类型。
语法:<类型>值
值 as 类型

二、类

TypeScript 是面向对象的 JavaScript,它描述了所创建的对象共同的属性和方法。

1、基本语法:

   class c{
          属性:类型,Eg: name:string;
          构造函数,Eg: constructor(name:string){
              this.name=XXX
          }
          方法,Eg: dis():void{
              console.log(123)
          }
          静态属性/方法:static age:number=1
                         static fn():void{
                             console.log(11)
                         }
          只读属性/方法:randonly 
          静态+只读 :static randonly name:number=18;
      }

静态(static)属性:在属性/方法前加上static则表示该属性是静态属性(类属性)
只读(readonly)属性:在属性/方法前加上static则表示该属性是只读属性,不可修改

2、类的继承

1.类继承使用关键字 extends,子类除了不能继承父类的私有成员(方法和属性)其他的都可以继承。
2. 继承可以将多个类中的共有代码写在一个父类中,子类想写一些额外的方法、属性 直接加就可以。
3. 子类同名方法会覆盖父类方法.
4.一个子类只能继承一个父类.
在子类中添加额外的属性时,则需要constructor()并且必须加super(),它表示调用父类的构造函数,super()参数为父类的属性值
在子类中不写constructor(),则在new出新对象时,将父类的属性值作为参数传入

class Animal {
            name: string;
            age: number;
            constructor(name: string, age: number) {
                this.name = name
                this.age = age
            }
            eat(): void {
            console.log('animal')
            }
                }
        class cat extends Animal {
              eat(): void {
                console.log('cat')
            }
            xixi: string;
            constructor(xixi: string) {
                super('猫', 5)
                this.xixi = xixi
             }
            }
        var xiaoxiao = new cat('喵喵~')

3、抽象类

当一个class只想让它作为超类被继承不需要直接利用它创建对象的时候,则加abstract使它成为抽象类。

abstract class Animal{
            name:string;
            age:number;
            constructor(name:string,age:number){
                this.name=name
                this.age=age
            }
          abstract eat():void{}
         }   

抽象方法只能创建于抽象类中,无方法体,需要子类对其重写

类中属性的封装

可以使用访问控制符来保护对类、变量、方法和构造方法的访问,有三种修饰符:
1.public(默认) : 公有,可以在任何地方被访问。
2.protected : 受保护,可以被其自身以及其子类访问。
3.private : 私有,只能被其定义所在的类访问。

 class Encapsulate { 
                 public str1:string = "hello" 
                 private str2:string = "world" 
                 protected str3:string='hi'
                 public fn():void{
                      console.log(this.str2)
                }
            }
            class children extends Encapsulate{
              fn():void{
                 console.log(this.str1,this.str3) //可访问
                 console.log(this.str2) //编译错误, str2 是私有的
                  }
            }
            var objs = new Encapsulate() 
            var child=new children()
            child.fn()
            console.log(objs.str1)     // 可访问 
            console.log(objs.str2)   // 编译错误, str2 是私有的
            console.log(objs.str3)   // 编译错误, str3 是受保护的

注意:加了protected修饰符的属性/方法,虽然子类可以访问,但是实例化出来的对象依旧不可以
私有属性可以通过公有方法暴漏出来。
4. 类中的getter、setter: 属性可以通过,getter、setter方法修改、调用(私有、保护同样适用)

   class Encapsulate { 
            public _str1:string = "hello" 
            private _str2:string = "world" 
            protected _str3:string='hi'
            get str2(){
                return this._str2
            }
            set str2(a:string) {
                if(a=='555'){
                    this._str2= a
                }else{
                    this._str2=this._str2
                }  
            }
        }
        var objs = new Encapsulate() 
        objs.str2='555' //相当于=右边的就为set的参数,可以实现对属性赋值前进行赋值判断
        console.log(objs.str2)//直接点语法则相当与调用get方法

注意:get set和本身的属性不要重名 并且该方法只存在于es5以上。
在实际开发中:
get方法去设定复杂属性,即与该类中的其他属性有关的属性.
set方法则是当自身属性与其他类种某些属性相关时,调用,进行自身属性的判断->修改。

三、接口

接口是一系列抽象方法的声明,是一些方法特征的集合,这些方法都应该是抽象的,需要由具体的类去实现。

interface IPerson { 
    firstName:string, 
    lastName:string, 
    sayHi: ()=>string /sayHi(): string 意思相同 
} 

接口中所有属性方法不可以有确定值,它和类型声明很像,区别是它是一个关键字 接口名,{}而类型声明是关键字 类型名={}

  type myType= { 
                firstName:string,  
                sayHi(): string 
            } 
        interface myInterface{ 
                firstName:string, 
                sayHi(): string 
            } 

想要使用接口来表示数组时,可以为数组的索引值和数值设置不同的类型:

interface arr { 
   [index:number]:string 
} 
var test:arr;
test[0]='hi'

该接口表示,实现了arr这个接口的变量应满足索引值为number类型,值为string类型。

此外interface可以重复声明,最终取合集;而类型声明不可以,只能一次声明。
接口类似于一个抽象类,它所有的值不能有实际值,也就是说它中的方法是抽象方法,类实现接口的语法格式:

   class myClass implements myInterface{
                    firstName:string
                    coonstructor(firstName:string){
                        this.firstname=firstname
                    }
                    sayHi():string{
                        return 'Hi'
                    }
                }

接口是Ts独有的,编译后Js文件中不会体现。
接口继承就是说接口可以通过其他接口来扩展自己。Typescript 允许接口继承多个接口。

四、泛型

宽泛的类型,通常用于类和函数也可以用于接口
函数中的泛型见ts函数类型处。

泛型可以指定接口/类:

interface my{
lengths:number
}
function func<T extends my>(a:T):number{
    console.log(a.lengths,'HHH')
    return a.lengths
}
func({lengths:5})
当函数的参数所对应的泛型指定接口时,记得在调用此函数时以对象的形式传参,泛型指定类时同理。
class bb {
 name: string
    constructor(name: string) {
        this.name = name
    }
       }
function func<T extends bb>(a: T): string {
    console.log(a.name, 'HHH')
    return a.name
}
func({ name: '55' })

类中的泛型:当类中某属性类型不确定时声明它的时候用泛型,在实例化对象时在传入想要的类型。

class myClass<T>{
    name:T
    constructor(name:T){
        this.name=name
    }
}
const mc=new myClass<string>(name:'小孙')

当类作为一个参数传入另一个类时,也可以使用泛型:

class mySql<T>{
        add(info:T):boolean{
        console.log(info)
        return true
        }
    }

    class user{
        username:string|undefined;
        age:number|undefined;
    }
    var u=new user()
    u.age=19
    var db=new mySql()
    db.add(u)
;