本文次要讲述动态类型、类型注解、类型推断、泛型、类型定义文件、模块化、打包编译、装璜器、Metadata、设计模式

一、概述

1.ts是js的超集,ts在浏览器或者node环境上不会间接执行,而是通过编译器编译成js后执行

2.超集:ts蕴含了es5、es6的所有语法,同时还蕴含了本人的新个性(可选的动态类型和基于类的面向对象编程)

3.TS的劣势(绝对于JS):


二、ts环境

1.npm init -y (初始化 增加package.json文件)

1.npm install typescript@3.6.4 -g

2.tsc --init 初始化ts工程

3.手动编译执行ts:tsc demo.ts => 生成雷同文件名的demo.js文件 => 生成js文件后即可通过node demo.js去运行js文件

4.主动编译执行ts:

npm install -g ts-node编译执行 ts-node demo.ts

三、根底语法

1.编辑器提醒

let b = 123b = '123'   不非法 不可能将‘string’赋值给‘number’let b:number = 123;  残缺的定义类型
function tsMathDemo(data: {x:number,y:number }){  return Math.sqrt(data.x**2 + data.y **2)}tsMathDemo()       提醒报错tsMathDemo({x:3,y:4})    失常编译

const count: number = 2019
count就蕴含了所有number类型的办法 count. 编译器主动提醒

2.另外两种定义参数类型办法(类型别名)

type Point = {x: number,y: number}interface Point{x: number,y: number}function tsFunc(data: Point){  return}// 用法interface Point {  x: number  y: number}const point: Point = {  x: 3,  y: 5}

3.根底类型:number string null undefined symbol boolean void

const count: number = 123const teacherName: string = 'Nico'

4.对象类型

const teacher: {  name: string  age: number} = {  name: 'Dell',  age: 8}const numbers: number[] = [1, 2, 3]

5.类

class Person {}const dell: Person = new Person()

6.函数

const getTotal: () => number = () => {  return 123}

7.类型注解 type annotation 显示申明类型,通知ts变量是什么类型

let count: numbercount = 123

8.类型推断 type inference ts主动尝试剖析变量的类型

let countInference = 123
// 类型推断funcconst func = (str: string) => {  return parseInt(str, 10)}// 类型注解func1const func1: (str: string) => number = (str) => {  return parseInt(str, 10)}const date = new Date()

9.参数须要应用类型注解申明,防止调用时传参类型不对

function getTotal(firstNumber: number, secondeNumber: number) {  return firstNumber + secondeNumber}const total = getTotal(1, 2)

10.定义函数

function hello() {}const hello1 = function () {}const hello2 = () => {}function add(first: number, second: number): number {  return first + second}//不能有返回值function sayHello(): void {  console.log('hello')}// never 永远不可能执行实现function errorEmitter(): never{  throw new Error()  console.log(123)}//形参类型为解构赋值时的类型注解写法function add({ first, second }: { first: number; second: number }): number {  return first + second}const total = add({ first: 1, second: 2 })

11.联结类型

let temp: number | string = 123temp = '456'

12.数组

const arr: (number | string)[] = ['1', 2, 3]

13.type alias 类型别名

type User = { name: string; age: number }const objectArr: User[] = [{ name: 'dell', age: 12 }]class Teacher {  name: string  age: number}const objectArr2: Teacher[] = [new Teacher(), { name: 'bell', age: 14 }]

14.元组 tuple : 按程序限度类型

const teacherInfo: [string, string, number] = ['xxx', 'yyy', 2]//csvconst teacherList: [string, string, number][] = [  ['dell', 'male', 2],  ['dell', 'male', 2],  ['dell', 'male', 2]]

15.定义接口

interface Person {  name: string  age?: number // age可有可无,不肯定要有值  readonly tall: number // tall为只读,不可赋值  [propName: string]: any // 还能够有其余属性。属性名称类型为string,值能够为任意类型  say(): string // 得有一个say()办法,返回值为string}// 利用接口class User implements Person {  name = 'dell'  tall = 170  say() {    return 'say hello'  }  sex = 'female'}// 接口继承interface Teacher extends Person {  teach(): string}

16.接口申明函数类型

interface SayHi {  (word: string): string}const say: SayHi = (word: string) => {  return word}

17.定义类

class Person {  name = 'dell'  getName() {    return this.name  }}// 继承类class Teacher extends Person {  getTeacherName() {    return 'teacherName'  }  getName() {    return super.getName() + 'lee'; // 笼罩父类的getName,应用super对象调用父类被笼罩的办法  }}
class Person {// 传统写法  public name: string;  constructor(name: string){    this.name = name  }// 简化写法  constructor(public name: string) {}}

18.继承类

class Person {  constructor(public name: string){}}class Teacher extends Person {  constructor(public age: number){    super('name')  }}const teacher = new Teacher(28)

19.getter 和 setter

class Person {  constructor(private _name: string) {}  get name() {    return this._name  }  set name(name: string) {    this._name = name  }}const person = new Person('dell')console.log(person.name)person.name = 'dell_lee'   // 'dell_lee'

20.单例模式

class Demo {  private static instance: Demo  private constructor(public name: string) {} // 结构器设计为private,那么就不能间接在内部new Demo()去创立实例  static getInstance(name: string) {  //static将办法间接挂载在类下面,而不是挂载在类的实例上  if (!this.instance) {    this.instance = new Demo(name)  }  return this.instance  }}const demo1 = Demo.getInstance('dell') // 实际上demo1 === demo2了const demo2 = Demo.getInstance('nick') // 实际上demo1 === demo2了console.log(demo1.name) // dellconsole.log(demo2.name) // dell

21.抽象类

abstract class Geom {  abstract getArea(): number}class Circle extends Geom {  getArea() {    return 123  }}class triangle extends Geom{}   // 没实现抽象类中的getArea()编辑器会报错class square {}

四、ts配置等内容

1.代码扭转时主动编译代码到build目录下

"build": "tsc -w"  //package.json配置启动命令
"outDir": "./build"  // tsconfig.json配置

2.在文件发生变化的时候就会主动执行build目录下的crowller.js文件

npm i nodemon -D    // 检测整个我的项目下的文件变动,而后去做绝对应的动作。
"start": "nodemon node ./build/crowller.js"    //package.json配置启动命令

主动疏忽data文件下的所有文件变动。防止造成循环调用start命令。

"nodemonConfig": {    //package.json配置项  "ignore": [    "data/*"  ]},

联合下面的build命令,那么通过批改文件,就会主动编译生成js文件,再通过nodemon去监测文件的变动主动执行相应的操作

3.同时执行多条命令,解决以上的build以及nodemon命令须要别离开一个终端能力执行。

npm i concurrently -D
"scripts": {    //package.json配置  "dev:build": "tsc -w",  "dev:start": "nodemon node ./build/crowller.js",  "dev": "concurrently npm:dev:*"},

将package.json中的scripts命令配置成这样,npm:dev:* 会泛匹配执行所有名为dev:build、dev:start等命令

4.npm参数-D和-S的区别

--save-dev(也就是-D) 装置的 插件,被写入到 devDependencies对象外面去;而应用 --save(-S) 装置的插件,则被写入到 dependencies 对象外面去。
devDependencies 外面的插件只用于开发环境,不用于生产环境,而 dependencies 是须要公布到生产环境的。

5.tsConfig.json文件配置

<1>指定只编译或者不编译的文件:

"include": ["./demo.ts"],"exclude": ["./demo.ts"],

<2>增量编译,只编译较上次更新的内容:

"incremental": true,

<3>容许JS文件也能够编译:

"allowJs": true,

<4>把所有要输入的文件,放到一个文件里去

"outFile": "./",

更多配置查阅ts官网documents选项中的tsconfig.json


五、爬虫

npm init -y 生成package.json
tsc -init 生成tsconfig.json
npm install -D ts-node (-D相当于 --save-dev 装置在我的项目dev中)
配置src目录及爬虫文件 配置dev命令

npm install superagent --save 发申请取得数据
npm install @types/superagent -D 翻译文件使ts能解析superagent依赖包

npm install cheerio -D 提取数据的依赖
npm install @types/cheerio -D 翻译文件

node外围模块 fs、path判断和读写文件

函数职责明确 尽量return返回值,再去获取返回值传给下一个须要调用的函数


六、ts高级语法

1.联结类型和类型爱护

<1>类型爱护之类型断言

interface Bird {  fly: boolean;  sing: () => {};}interface Dog {  fly: boolean;  bark: () => {};}function trainAnial(animal: Bird | Dog) {  if (animal.fly) {    (animal as Bird).sing();  } else {    (animal as Dog).bark();  }}

<2>类型爱护之in语法

function trainAnial(animal: Bird | Dog) {  if('sing' in animal){    animal.sing();  }else{    animal.bark();  }}

<3>类型爱护之typeof

function add(first: string | number,second: string | number){  if(typeof first === 'string' || typeof second === 'string'){    return ${first}${second}  }  return first + second}

<4>类型爱护之instanceof

class NumberObj {  count: number;}function addSecond(first: object | NumberObj, second: object | NumberObj) {  if (first instanceof NumberObj && second instanceof NumberObj) {    return first.count + second.count;  }  return 0;}

2.枚举类型

// 枚举类步长为1,默认0开始enum Status {  OFFLINE, //0  ONLINE, //1  DELETED, //2}console.log(Status[1]); // ONLINEconsole.log(Status.OFFLINE); // 0function getResult(status: number) {  if (status === Status.OFFLINE) {     return "offline";  } else if (status === Status.ONLINE) {    return "online";  } else if (status === Status.DELETED) {    return "deleted";  }  return "error";}getResult(Status.ONLINE); // online

3.函数泛型

//  泛型 generic 泛指的类型function join

4.类的泛型以及泛型类型

<1>类的泛型根底用法

class DataManager<T> {  constructor(private data: T[]) {}  getItem(index: number): T {    return this.data[index];  }}const data = new DataManager<string>(["1"]);console.log(data.getItem(0));

<2>泛型继承inteface

interface Item {  name: string;}class DataManager<T extends Item> {  constructor(private data: T[]) {}  getItem(index: number): string {    return this.data[index].name;  }}const data = new DataManager([{ name: "dell" }]);const res = data.getItem(0);

<3>类的泛型束缚

class DataManager<T extends number | string> {  constructor(private data: T[]) {}  getItem(index: number): T {    return this.data[index];  }}interface Test {  name: string;}// const data = new DataManager<Test>([]); // 报错,类型“Test”不满足束缚“string | number”const data = new DataManager<number>([1]);console.log(data.getItem(0));

<4>如何应用泛型作为一个具体的类型注解

// 如何应用泛型作为一个具体的类型注解function hello<T>(params: T) {  return params;}const func: <T>(params: T) => T = hello;

4.namespce命名空间

<1>这会生成四个全局变量,但实际上只须要生成一个Page变量即可

class Header {  constructor() {    const elem = document.createElement("div");    elem.innerText = "This is Header";    document.body.appendChild(elem);  }}class Content {  constructor() {    const elem = document.createElement("div");    elem.innerText = "This is Content";    document.body.appendChild(elem);  }}class Footer {  constructor() {    const elem = document.createElement("div");    elem.innerText = "This is Footer";    document.body.appendChild(elem);  }}class Page {  constructor() {    new Header();    new Content();    new Footer();  }}

用namespace能够躲避过多产生不必要的全局变量,编译后只产生命名空间Home这一个全局变量:

namespace Home {  class Header {    constructor() {      const elem = document.createElement("div");      elem.innerText = "This is Header";      document.body.appendChild(elem);    }  }  class Content {    constructor() {      const elem = document.createElement("div");      elem.innerText = "This is Content";      document.body.appendChild(elem);    }  }  class Footer {    constructor() {      const elem = document.createElement("div");      elem.innerText = "This is Footer";      document.body.appendChild(elem);    }  }  export class Page {    constructor() {      new Header();      new Content();      new Footer();    }  }}
<body>  <script src="./dist/page.js"></script>  <script>    new Home.Page()  </script></body>

<2>模块化命名空间

tsconfig.json配置,将所有文件打包输入到一个文件内,使命名空间之间能够相互调用(能够查看编译过后的js文件,变量都在一个文件内申明,能够相互拜访):

"module": "amd","outFile": "./dist/page.js",

次要调用的命名空间文件page.ts

///<reference path='./components.ts' />// 应用reference申明以后命名空间援用的其它命名空间,不便后续浏览代码namespace Home {  export class Page {    user: Components.user = { name: "dell" }; // 援用其它命名空间的接口interface    constructor() {      new Components.Header();      new Components.Content();      new Components.Footer();    }  }}

提取进去的命名空间文件components.ts

namespace Components {  export namespace SubComponents {    // 子命名空间,能够再控制台通过Components.SubComponents.Test拜访到子命名空间抛出来的内容    export class Test {}  }  export interface user {    name: string;  }  export class Header {    constructor() {      const elem = document.createElement("div");      elem.innerText = "This is Header";      document.body.appendChild(elem);    }  }  export class Content {    constructor() {      const elem = document.createElement("div");      elem.innerText = "This is Content";      document.body.appendChild(elem);    }  }  export class Footer {    constructor() {      const elem = document.createElement("div");      elem.innerText = "This is Footer";      document.body.appendChild(elem);    }  }}

index.html文件:

<body>  <script src="./dist/page.js"></script>  <script>    new Home.Page()  </script></body>

5.parcel打包

官网文档:github.com/parcel-bundler/parcel;
装置:npm i parcel@next -D;
package.json配置scripts命令:

"start": "parcel ./src/index.html"    // 运行该命令就会启动一个服务器

6.形容文件中的全局类型

index.html引入jQuery:https://cdn.bootcss.com/jquer...
失常状况下ts不会解析jQuery语法,须要装置形容文件:

npm i @types/jquery

本人试着手写解析 $选择器的类型形容文件:

<1>page.ts内容:

// 第一种$(function () {  alert("123");});// 第二种$(function () {  $("body").html("<div>123fsa</div>");});// 第三种$(function () {  new $.fn.init();});

<2>jquery.d.ts类型形容文件:

//办法一// declare定义全局变量$,接管的参数为一个函数,返回值为空void。// declare var $: (param: () => void) => void;//办法二//declare定义全局函数;interface JqueryInstance {  html: (html: string) => JqueryInstance;}declare function $(readyFunc: () => void): void;    // 第一种declare function $(selector: string): JqueryInstance;    // 第二种declare namespace $ {    // 第三种,对对象进行类型定义,以及对类进行类型定义,以及命名空间的嵌套  namespace fn {    class init {}    // 因为是new $.fn.init(),所以init()是一个构造函数,所以应用class去定义 init()  }}

<3>jquery.d.ts类型形容文件的优化版本:

//应用interface接口申明函数类型的语法,实现函数重载interface JqueryInstance {  html: (html: string) => JqueryInstance;}interface JQuery {  (readyFunc: () => void): void;  (selector: string): JqueryInstance;}declare var $: JQuery;//应用interface接口申明函数类型的语法,实现函数重载interface JqueryInstance {  html: (html: string) => JqueryInstance;}interface JQuery {  (readyFunc: () => void): void;  (selector: string): JqueryInstance;}declare var $: JQuery;

<4>ES6模块化的类型形容文件写法:

将script引入cdn门路办法改成:npm i jquery --save装置,而后应用import导入

import $ from 'jquery'$(function () {  $("body").html("<div>123fsa</div>");  new $.fn.init();});
//Es6模块化declare module "jquery" {    // 定义的module名称要与import的统一  interface JqueryInstance {    html: (html: string) => JqueryInstance;  }  // 混合类型  function $(readyFunc: () => void): void;  function $(selector: string): JqueryInstance;  namespace $ {    namespace fn {      class init {}    }  }  export = $;    // 导出$}

七、