TypeScript学习笔记

99 阅读7分钟

image.png

联合类型

|分隔多个类型 表示取值可以为多个类型中的一种

类型别名

//用type 定义类型别名
type MyType = 1|2|3|4|5
let k:MyType = 2

枚举类型

不确定类型时尽量用unknow,不用any,unknow类型的字段不能直接赋值给已知类型的字段,必须要先确定其类型后再赋值给别人,可以用断言方式,也可以用泛型方式赋值

let e:unknown
let s:string
e='hellow'
e = 10
e = true
// s=e as string 
s = <string> e
console.log(s)//true

枚举类型

关键字enum

enum Gender{male,female }//如果枚举成员没有被赋值,那么他们的值会按照从0开始的索引开始被一次复制,这里相当于male=0,female=1
let o:{name:string,gender:Gender}
o = {
  name:'孙悟空',
  gender:Gender.male
}
console.log(Gender.male === 0) //true
console.log(o.gender == Gender.male) //true

手动赋值

enum Gender{male=1,female=0 }
let o:{name:string,gender:Gender}
o = {
  name:'孙悟空',
  gender:Gender.male
}
console.log(Gender.male === 1) //true
console.log(o.gender == Gender.male) //true
## 对象类型-接口 

```typescript
interface Person{
 name:string;
 age?:number;
 [propName:string]:any;
}

定义对象类型(规格型号),可以用于对类的一部分进行抽象,还可以用于对对象的形状进行描述

interface 中的属性支持逗号、分号,不要符号三种分隔方式

可选属性

表示对象的该属性可以不存在,形式为:属性名?:类型 age?:number

任意属性

表示一个接口可以有任意属性,形式为:[propName:类型]:类型,注意定义了任意属性的值类型后,接口其他属性的值类型必须为任意类型属性子类型集

interface Person{
 name:string
 age:number
 [propName:string]:string|number
}

只读属性

对象中某个属性只能创建的时候被赋值,可以用readonly定义

interface Person{
    readonly id: number
    name: string
    age?:number
}
let tom:Person={
    name:'Tom',
    age:16
}
tom.id=12345

数组类型

有多种表示法

类型+方括号表示法

let a:number[]=[1,2,3] 数组元素只能是number类型

泛型数组:Array<elemType>

let a:Array<number> = [1,2,3]

any不限制数组元素类型

let list:any[] = [1,'a',null,{name:'aaa'}]

元组 Tuple

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

长度固定的数组,元组存储效率会好于数组

函数类型

js中函数定义有函数声明和函数表达式两种方式

函数声明

函数的输入和输出类型约束

function sum(x:number,y:number):number {
    return x + y
}
sum(1,2)

上面定义的函数如果多传入或少传入参数,ts中都会报错(可选参数和任意参数除外)

函数表达式

let sum = function(x:number,y:number):number {
    return x + y
}

=>表示函数输出类型

let sum:(x:number,y:number)=>number = function(x:number,y:number):number {
    return x + y
}

void 表示函数没有返回值

void和never区分就是void表示返回的时空的,有返回,但没有值,never是直接不返回了

function myfun():void{
    
}

可选参数

与接口中的可选属性类似,可选参数只能出现在必选参数后面

function buildName(firstName:string,lastName?:string) {
    if(lastName){
      return firstName + '' + lastName
    }else{
      return firstName
    }
}

参数默认值

(paramName:paramType=默认值)

rest参数

...变量名,和ES6的rest参数一样,rest参数只能是最后一个参数 ES6的rest参数:类似arguments,但rest参数返回的是数组类型,arguments是对象类型

image.png

重载

允许一个函数接受不同数量或类型时做出不同处理

function reverse(x:number):number;
function reverse(x:string):string;
function reverse(x:number|string):number|string{
    if(typeof x === 'number'){
        return Number(x.toString().split('').reverse().join(''))
    }else if(typeoof x === 'string'){
        return x.split('').reverse().join('')
    }
}

类型断言

用于手动指定一个值的类型 语法如下:

as 类型(推荐)
<类型>值

应用

将一个联合类型断言为其中一个类型

interface Cat {
    name:string;
    run():void;
}
interface Fish {
    name:string;
    swim():void;
}
function isFish(animal:Cat|Fish){
    //想要获取联合类型的具体方法,就要将联合类型断言成指定的一种类型
    if(typeof (animal as Fish).swim === 'function'){
        return true
    }
    return false
}

属性和方法

类用于创建对象模型,类中有两块内容:属性方法 属性和方法如果在前面加了static关键字则表明是静态的属性和方法,也就是类自身的属性和方法,是不可以被修改的,可以直接通过类访问,不需要通过实例去获取,没有static关键字的则表示是实例的属性和方法,可以被修改。

class Person {
  name:string = '孙悟空'
  age:number = 18
  static name1 = '猪八戒'
  sayHello(){
      console.log(this.name)
  }
  static sayHello1(){
    console.log(Person.name1)
  }
 }
 let swk = new Person()
 swk.sayHello()
 swk.name = 'tom'
 swk.sayHello()
 Person.sayHello1()
 //输出
 孙悟空 18
 tom 18
 猪八戒

构造函数

在用new创建实例对象时实际就是调用累的constructor函数

class Person{
  name:string
  constructor(name:string){
    this.name = name
  }
  sayHello(){
    console.log('my name is '+this.name)
  }
}
let tom = new Person('tom')
let lisa = new Person('lisa')
console.log(tom) 
tom.sayHello()
lisa.sayHello()
//输出
Person { name: 'tom' }
my name is tom
my name is lisa

类的继承

子类继承父类,相当于子类拷贝了父类中的属性和方法,同时子类也可以有自己的方法和属性,如果子类中有和父类同样的方法,那么子类的方法会覆盖父类的方法,也就是重写了父类的方法。

class Animal {
  name:string
  age:number
  constructor(name:string,age:number){
    this.name = name
    this.age = age
  }
  sayHello(){
    console.log(this.name+'在叫 ')
  }
}
class Dog extends Animal{
  run(){
    console.log('我会跑')
  }
}
class Cat extends Animal{
  sayHello(){
    console.log('喵喵喵')
  }
}
let dog = new Dog('tom',5)
let cat = new Cat('xiaoli',3)
dog.sayHello()
cat.sayHello()
dog.run()
//输出
tom在叫 
喵喵喵
我会跑

属性封装

public private protected

类中用public修饰的属性或者方法表示是公有,可以在任何地方访问 类中用private修饰的属性或者方法表示是类的私有的,不能在类外部访问它,只能在类内部使用 类中用protected修饰的属性或者方法表示是受保护的,不能在类外部访问它,但可以在子类中使用 image.png

属性读写器getter setter

为了防止属性被任意篡改,比如年龄在外部被赋了个负值发生的危险,我们可以将类的属性控制前放在自身,读和写都有自己控制

(function(){
  class Person{
    private _name:string
    private _age:number
    constructor(name:string,age:number){
      this._name = name
      this._age = age
    }
    get name(){
      return this._name
    }
    get age(){
      return this._age
    }
    set name(value:string){
      this._name = value
    }
    set age(value:number){
      if(value > 0){
        this._age = value
      }
    }
  }
  let p = new Person('lisa',19)
  p.name='tom'
  p.age = -10
  console.log(p.name,p.age) //tom,19
})()

readonly

在类中用readonly定义的属性不可以被修改,表示只能读不能写

super

super 表示当前子类的父类,如果子类的构造函数中,必须调用父类的构造函数

class Animal {
  name:string
  age:number
  constructor(name:string,age:number){
    this.name = name
    this.age = age
  }
  sayHello(){
    console.log(this.name+'在叫 ')
  }
}
class Dog extends Animal{
  constructor(name:string,age:number){
    super(name,age)
  }
  run(){
    console.log('我会跑')
  }
}

抽象类 abstract

abstract定义的类,不可以被实例化,这叫抽象类,通常用来定义被子类继承的父类,抽象类里也可以定义抽象方法,定义了抽象方法后,子类就必须重写该抽象方法

abstract class Animal {
  name:string
  age:number
  constructor(name:string,age:number){
    this.name = name
    this.age = age
  }
  abstract sayHello():void
}
class Dog extends Animal{
  sayHello(): void {
    
  }
}
let dog = new Dog('狗',4)

类实现接口 implements

定义类时可以让类去实现一个接口,也就是按照一个接口的标准去定义并实现,实现接口就是让类满足接口的条件; 接口是为了定义一个标准,来约束类,让类必须按照接口来实现,接口里定义的方法没有具体实现内容,就是为了让类去实现这个方法的。

interface MyInter{
  name:string
  sayHello():void
}
class MyClass  implements MyInter{
  name:string
  constructor(name:string){
    this.name = name
  }
  sayHello(): void {
    console.log(this.name)
  }
}
let c = new MyClass('zs')
c.sayHello()

泛型

在定义函数或类时,遇到不确定的类型可以用泛型表示,泛型可以指定多个,表达方式是<T,K,....>

function fn<T,K>(a:T):T{
  return a
}
let res = fn(10)
let res1 = fn('10')
// 泛型类
class MyClass<T>{
  name:T
}
// 泛型约束
interface LengthWise{
  length:number
}
//T extends LengthWise 表明泛型T必须为LengthWise的实现类
function loggingIndentity<T extends LengthWise>(arg:T):T{
  console.log(arg.length)
  return arg
}
loggingIndentity({length:10})//10
loggingIndentity('111')//3
loggingIndentity(1) //1没有length属性

迭代器

let list = [4,5,6]
//for... in 关注迭代对象的键
for (let i in list){
  console.log(i)//0,1,2
}
//for...of 关注迭代对象的值
for (let i of list){
  console.log(i) //4,5,6
}