typescript基础

typescript简介

typescript是javascript的一个超集,支持ES标准。在js的基础上通过类型注解,提供编译时的静态类型检查,可以编译成纯javascript代码,从而运行在浏览器与node上。

优势:

  • 开发过程中,就发现潜在的问题。而非像js一样,执行才会报错
  • 更友好的编辑器代码提示
  • 代码语义更清晰易懂,无须深入代码逻辑

环境配置

  • node环境
  • 全局安装typescript: npm install typescript -g,使用命令tsc编译ts文件
  • 全局安装ts-node:npm install ts-node -g,可直接运行ts文件

数据类型

类型分类

主要分为基础类型与对象类型,基础类型包括:nullundefinedbooleannumberstringsymbolvoid等,对象类型包括:函数数组对象

// 基础类型
const personName: string = 'zhangsan';
const isMale: boolean = true;
const age: number = 18;

// 对象类型
class Person { }

const teacher: {
    name: string,
    age: number
} = { name: 'kahn', age: 19 }

const numbers: number[] = [1, 2]

const person: Person = new Person();

const getTotal: () => number = () => {
    return 123
}
function getTotal2(): string {
    return '123'
}

类型注解&类型推断

类型注解:显示的指定变量的类型。如:

let count: number;
count = 123;

类型推断:不指定变量的类型,直接对变量进行赋值。ts会自动的尝试分析变量的类型。如:

let count = 123;

简单的数据类型如基础类型,ts可自动识别出来的类型,可不使用类型注解,而自定义的数据结构如嵌套数组、对象、函数等,则最好使用类型注解。

函数类型相关类型

函数定义时,尽量将参数使用显示类型注解方式进行申明,而返回值不强制要求申明类型,看具体的情况决定。便于代码的阅读与报错检验,如:

function add1(num1: number, num2: number): number {
      return num1 + num2;
}

function add2({num1, num2} : {num1: number, num2: number}): number {      //解构类型参数的注解写法
      return num1 + num2;
}

function string2num: (str: string) => number = (str) => {
      return parseInt(str);
}

function sayHello(): void {      //void表示函数没有返回值
      console.log('hello');
}

function errorEmitter(): never {      //never表示该函数没有办法执行完
      throw new Error();
}

数组&元组

数组注解:

let arr1: number[] = [1,2,3];
let arr2: (number | string) = [1,2,'3'];
let arr3: {name: string}[] = [{name: 'zhangsan'}]

interface Person {name: string};
let arr4: Person[] = [{name: 'kahn'}];

type alias User {name: string};
let arr5: User[] = [{name: '张三'}]

class Teacher {name: string};
let arr6: Teacher[] = [{name: '王老师'}]

元组注解:(数组的长度与元素的类型固定时就可以使用元组)

let personInfo: [string, string, number] = ['kahn', 'male', 25];
let personInfos: [string, string, number][] = [
      ['kahn', 'male', 25],
      ['zhou', 'male', 25]
]

接口

注解形式:

interface Person {
      name: string
}
const getPersonName = (person: Person) => {
      return person.name;
}
const setPersonName = (person: Person, name: string) => {
      person.name = name;
}
getPersonName({name: 'kahn', age: 12});            //会报错。以字面量的形式进行传递的时候,类型检查会比以变量进行缓存的方式更加严格
let person = {name: 'zhangsan', age: 18};
getPersonName(person);            //不会报错

上述中的Person也可以用类型别名type定义:type Person = {name: string},效果是一样的。(但Interface只能定义对象类型,type还可以单独定义基础类型,如type name = string)。

如果需要在接口中的某些属性不是必须,则可以加上?修饰符,如:

interface Person {
      name: string;
      age?: number;
}

属性只允许读:

interface Person {
      readOnly name: string
}

如果在接口中不确定是否需要在后期增加属性,可通过自定义属性方式,如:

interface Person {
      name: string;
      [proName: string]: any;
}
let person: Person = {name: 'kahn', class: '三年一班'};

接口中还可以定义方法:

interface Person {
      name: string;
      getName(): string;
}
let person = {name: 'kahn', getName: () => {return 'kahn'}}
class User implements Person {      //类应用接口
      name: 'zhangsan';
      getName: () => {
            return 'zhangsan'
      }
}

上述中使用类来应用接口,此外,接口还可以进行继承,如:

interface Person {
      name: string;
}
interface Teacher extends Person {
      age: number;
}
// 上面将name这样的通性部分提出来,便于后续通性方法的使用(只需要增加子类接口的实现即可)
let getPersonName: string = (person: Person) {
      return person.name;
}

接口也可以定义函数的类型申明,如:

interface sayHi {
      (word: string): string;
}
let say: sayHi = (word: string) => {
      return word;
}

定义与构造函数

typescript中类与ES6中的类比较相似,但ts中提供了更多的特性。基本定义:

class Person {
    name: string;            //ts中,需要提前定义类的属性,不像js中可以直接在this上通过"."或"[key]"的方式进行添加
    constructor(name: string) {
        this.name = name;
    };
    getName(): string {
        return this.name;
    }
}
class Teacher extends Person {
    getName(): string {
        return super.getName() + 'lee';      //当子类对父类中的方法重写时,而又需要用到父类方法时,可以使用super
    }
}

let person = new Person('kahn')
let teacher = new Teacher('张老师');

console.log(person.getName(), teacher.getName());

上述类中的构造器也可以直接对参数进行访问修饰符,从而省略内部变量的定义,属于简化写法。如:

class Person {
      constructor(public name: string) {

      }
}

当父类中有构造函数时,子类需要在自己的构造函数中使用super实现父类的构造函数。即使父类没有构造器,子类也需要在构造器中调用空的super()进行实现。

访问权限

TS中增加了对类中变量、函数、构造方面的权限访问,包括:

  • public(默认):公有。可以在类中、类外访问。可以直接通过示例对象的属性访问
  • private:私有。只允许在类中进行访问
  • protected:受保护。可以在类中或子类访问
class Person {
    public name: string;
    private age: number;
    protected sex: string;
}
class Teacher extends Person {
    getName(): string {
        return this.name + 'lee'
    }
    getAge(): string {
        return this.age;      //报错
    }
    getSex(): string {
        return this.sex;
    }
}

let person = new Person()
let teacher = new Teacher();

console.log(person.name);
console.log(teacher.name);
console.log(person.age);      //报错
console.log(person.sex);      //报错

getter与setter

class Person {
    constructor(private _name: string) {}      //私有属性一般加上下划线,便于后面的代码理解
    get name() {
        return this._name + 'xxx';      //通过添加尾部,或加密的方式,保护私有属性_name
    }
    set name(name: string) {
        this._name = name;
    }
}

let person = new Person('zhang')
console.log(person.name);      //调用getter的时候,无需编写函数执行的形式

使用类实现“单例模式”:

class Person {
    private static instance;

    private constructor(private _name: string) {};      //不允许使用new创建对象

    static getInstance(name: string) {      //使用类的静态方法,在类中创建对象,并只允许新建一次
        if (!this.instance) {
            this.instance = new Person(name);
        }
        return this.instance;
    }

    get name(): string {
        return this._name
    }
}

let person1 = Person.getInstance('zhang');
let person2 = Person.getInstance('zhou');
console.log(person1.name);      // zhang
console.log(person2.name);      // zhang

抽象类与抽象方法

使用关键字abstract定义抽象类与抽象方法,如下:

abstract class Geom {
    width: number;
    getType(): string {
        return 'geom'
    };
    abstract getArea(): number;
}

class Circle extends Geom {
    getArea() {
        return 123
    }
}

抽象类不允许创建实例,只能用于继承。抽象方法无需在父类中进行实现,定义即可,而在子类中必须对抽象方法进行实现。

编译

写好的ts文件是不能直接拿来用的,除非使用ts-node。此时要进行tsc的编译过程。

搭建环境:

  • 创建全局命令tscnpm install typescript -g
  • 项目中执行npm inittsc --init,前者是npm初始化生成package.json,后者是typescript配置初始化,生成tsconfig.json
  • 在package.json中增加script命令:"build": "tsc",在tsconfig.json中设置编译后的文件路径outDir
  • 项目根目录中执行命令:npm run build,即可在outDir定义的目录中查看到编译后的js文件

如果需要实时的监听ts文件的改动,并自动编译的话,在package.json中的build命令中,添加-w参数即可

再更一步需要编译后,自动执行,可以使用nodemon,使用npm install nodemon -D,然后在package.json中设置脚本"start": "nodemon ./build/xxx.js",然后控制台执行npm run start即可(注意nodemon是监听项目中所有文件的变化,包括文档,但不包括ts。如果需要忽略,则需要按照官方进行设置)

tsc -w可与nodemon在两个窗口之间配合使用,也可以使用concurrently将两个命令组合起来进行使用

posted @ 2021-08-20 16:37  Mr_Kahn  阅读(55)  评论(0)    收藏  举报