记录TypeScript 的一些基础知识

713 阅读4分钟

背景

下面是TS的一些基础知识,确实有点宽泛,加深自己的理解,之后,还会针对不同的知识点来写文章

基础类型

数组

const arr1: string[] = ['123'];

const arr2: Array<string> = ['qwe'];

类型断言

通过类型断言这种方式可以告诉编译器,“相信我,我知道自己在干什么”。 类型断言好比其它语言里的类型转换,但是不进行特殊的数据检查和解构。 它没有运行时的影响,只是在编译阶段起作用。

有两种方式,一种是尖括号的形式,<类型> xxx, 另一种是as的形式 (xxx as string)

function getLength (n: string | number) {
  if ((<string>x).length) {
      return (x as string).length;
      } else {
        return x.toString.length;
      }
}

类型推断

接口 interface

函数类型

接口除了可以描述普通的对象之外,也可以描述函数类型

interface SearchFun {
  (source: string, str: string): boolean
}
// 定义一个函数,该类型就是上面定义的接口
let search: SearchFun = function (source: string, str: string): boolean {
  return source.search(str) > -1;
}

类类型

总结: 接口和接口之间叫继承, 类和接口之间叫实现


interface Fly {
    flys(): void
}

class TheFly implements Fly {
    flys() {
        console.log('1');
    }
    adb () {
        
    }
}
// 2
interface Flys {
  sendFly():void
}
class Person implements Fly, Flys {
  sendFly () {
    
  }
  flys() {
        console.log('1');
  }
}
// 定义一个接口,可以继承多个接口
interface MoreFly extends Fly, Flys {
  
}

// 

类和类之间如果要有继承关系,需要使用extends关键字

子类中可以调用父类中的构造函数,使用的是super关键字

子类中可以重写父类中的方法

// TS 中类的定义和使用

class Person {
  name: string
  age: number
  constructor (age: number = 12) {
    this.age = age;
    this.name = '1';
  }
  sayHi (name: string) {
    console.log('1')
  }
}
class Students extends Person {
  constructor (age: number) {
    // 调用父类中的构造函数
    super(age)
  }
  // 可以调用父类中的方法
  sayHi () {
      super.sayHi('qwe');
  }
}

多态

父类型的引用指向了子类型的对象

不同类型的对象针对相同的方法,产生了不同的行为

类中成员的修饰符 public private protected readonly

public 默认的访问修饰符,代表公共的,任何位置都可以访问类中的成员

private修饰符 私有属性,只能在类中使用,不能在类外面使用,特别是子类中也是无法使用的

protected 修饰符,外部是不能使用的,子类中可以使用

readonly 修饰符,对类中的属性进行修饰,但是,不能在外部修改了;但是,构造函数中,可以对只读的属性进行修改

一旦使用readonly进行修饰之后,就有了一个age属性成员

下面的例子,修饰器还可以用在构造函数的参数上

class Person {
  name: string
  constructor (readonly age: number = 12) {
    this.age = age;
    this.name = '1';
  }
  sayHi (name: string) {
    console.log('1')
  }
}

存取器 get set

截取对象成员的访问


class Person {
    firstName: string = 'liu'
    lastName: string = 'yongsheng'

    get fullName () {
        return this.firstName + '_' + this.lastName;
    }

    set fullName (val) {
        let name = val.split('_');
        this.firstName = name[0];
        this.lastName = name[1];
    }
}

let p = new Person();
// 注意fullName 不是函数
console.log(p.fullName);

p.fullName = 'abc_qwe';

静态成员 static

在类中通过static修饰的属性或者方法

静态成员是通过类名+'.' 的形式来访问的(Person.abc

这些属性存在于类本身上面而不是实例对象上面

/*
	静态属性,是类对象的属性
	非静态属性,是类的实例对象的属性
  static不能出现在构造函数的前面
*/
class Person {
  static name:string = 'lys'
}
console.log(Person.name);

抽象类 abstract

抽象类作为其他派生类的基类使用。

抽象类不能被实例化

抽象类里面的抽象方法,不能有具体的实现

abstract class Animal {
  abstract eat():void
  // 报错,不能有具体的实现
  // abstract eat():void {
  //     console.log('eat');
  // }
}
class Dog extends Animal {
    // 重新实现抽象类中的方法
    eat () {
        console.log('111');
    }
}
// let bird = new Animal(); 报错,抽象类是不能被实例化的

TS中的函数

可选参数和默认参数

const fun = function (a: string = 'dongfang', b?: number): string {
  
}

剩余参数 ...rest

rest参数,一定要放在函数声明的时候的所有参数之后

function Fun (a: string, ...args: string[]) {
  
}
Fun('q', 'qw', 'e', 'r');

函数重载

函数的名字相同,但是函数的参数及个数是不同的

// 函数重载的声明
function add(x: string, y: string): string
function add(x: number, y: number): number

function add(x: string | number, y: string | number): string | number | undefined {
    // 在实现上我们要注意严格判断两个参数的类型是否相等,而不能简单的写一个 x + y
    if (typeof x === 'string' && typeof y === 'string') {
      return x + y
    } else if (typeof x === 'number' && typeof y === 'number') {
      return x + y
    }
  }

泛型

在定义函数,接口,或者类的时候,不能确定要使用的类型,而是在使用的时候,确定要使用的类型

// 多个泛型参数的函数
function getMsg<K,V> (val1: K, val2: V): K[] {
  return [val1];
}

声明文件