# TypeScript

#  一、概述 

# 1、什么是Typescript?

官方网站的定义是: TypeScript 是 JS 类型的超集TypeScript 是一个js的外壳,需要编译成浏览器可识别的javascript才可以运行。

# 2、为什么使用Typescript?

  • 弥补javascript缺少类型判断,缺少结构化机制(类、模块、接口等)的不足

  • 程序更容易理解 (‘代码即注释’)

  • 效率更高(编译期就会发现大部分错误)

  • 非常好的包容性(完全兼容js、流行项目都支持Ts)

    不足:增加了一些学习成本,短期内增加了一些成本,项目规模小,无必要使用

# 2、安装和初试

  • 安装
npm install -g typescript
  • 编译
tsc file.ts
  • 简便方法,安装ts-node

    每次都需要对ts文件编译产生js文件后再通过node 运行,比较麻烦

npm i ts-node -g
ts-node file.ts

# 3、数据类型

  • 原始数据类型

    • Boolean

      let isDone: boolean = false;

    • Null

      let null = null

    • Undefined

      let undefined = undefined

    • Symbol

    • String

      let firstName:string = "jimmy"

    • Number

      let age: number = 20 | 0b1111;

      注意: undefined和null是其他类型的子集

    Eg:

    let num: number = undefined | null

  • any类型,有明确类型避免使用

let notSure :any = 4

notSure = '1233'

notSure = true

  • 联合类型(|)

let numberOrString : number | string = 23

  • 数组类型

let arrOfNumbers:number[] = [1,2,3,4]

arrOfNumbers.push(1)

arrOfNumbers.push('1') // error

  • Tuple--特殊定义数组类型的方式

let user:[string,number] = ['hello', 99]

user = ["world","haha"] // error

  • interface

| 对对象的形状进行描述

| 对类进行抽象

| 鸭子类型 对象的推断,而不是对象本身

interface IPerson{
  readonly id:number;
  name:string;
  age?:number;
}
let tom: IPerson = {
  name : 'tom',
  id:1,
  age:19
}
// 注意: age后面的问号代表可选属性,代表该属性可以不存在,readonly代表只读属性,代表对象中的该属性只能读不能修改。注意接口命名首字母需要大写,I开头不强制, 每个属性定义后用";" 结尾
  • 函数类型
// 对参数和返回值的约定
const add = function(x:number,y:number,z?:number =10):number{
    if(typeof  m === 'number'){
        return x + y + m
    }else{
        return x + y
    }
}
// let result = add(1,2)
// let result = add(1,2,3)
// z为可选类型可选类型放参数最后面

// 类型推断,可以根据赋值推断变量类型
const add2: string = add  // error
const add2:(x:number,y:number,z?:number =10)=>number = add   // true
eg:
let str = "hello"
str = 123      // error
str = "world"  // true
  • class类的支持
// 创建Animate类
class Animate{
  public name:string;   // 公有属性|默认属性
  readonly id:number;   // 只读,不可修改赋值
  private size:number;  // 私有方法,只有自己可以访问
  protected key:boolean;// 受保护的属性,自己和子类可以使用
  static categoies:string[] = ["mammal",brid];  // 静态属性
  static isAnimal(a){    // 静态方法
    return a instanceof Animate
  }
  constructor(name){
    this.name = name;
  }
  run(){
      return `${this.name} is running`
  }
}
// 继承父类
class  Cat extends Animate{
  constructor(name,key){
    super(name) // 继承父类的方法
    this.name = name;
    this.key = key;
    run(){   // 重写父类run方法
      return 'Meow, ' + super.run()
    }
  }
}
const cat = new Cat('miao',true)
console.log(cat.run())  // 'Meow, miao is running'
  • 类和接口的使用---implements
// 提取公共的接口
interface Radio{
  switchRadio(trriger:boolean) : void | number;
}
// Cellphone特有
interface Battery{
   checkBattertStatus();
}
class Car implements Radio{
  switchRadio(){}
}
class Cellphone implements Radio,Battery{
  switchRadio(){}
 checkBattertStatus(){}
}

// 定义接口继承已有
interface RadioWithBattery extends Radio{
   checkBattertStatus();
}
class Cellphone implements checkBattertStatus{
  switchRadio(){}
 checkBattertStatus(){}
}
  • 枚举Enums

一般声明常量中使用,并且有一定关系

数字枚举

enum Direction{
    Up,
    Down,
    Right,
    Left
}
console.log(Direction.Up)   // 0
console.log(Direction.Down) // 1
console.log(Direction[0])   // Up
可以给Up赋值,后面的会递增

字符串枚举

enum Direction{
    Up='UP',
    Down='DOWN',
    Right='RIGHT',
    Left='LEFT',
}
const value = 'UP'
if(Direction['UP']===value){
  console.log('go up')
}

常量枚举

只需要在枚举前面加const,会内联枚举,提高计算性能

const enum Direction{
    Up='UP',
    Down='DOWN',
    Right='RIGHT',
    Left='LEFT',
}
  • 泛型----generics

    泛型出现的动机和要解决的问题:

    在定义时没办法确定参数类型和返回类型的时候,在使用时才能确定

    可以简单理解为占位符,动态指定类型

function echo(arg:number){
  return arg
}
const result = echo(123)   // result is number
const result = echo('123') // result is string change arg is string

...

result无法随意匹配any类型

改造后:

function echo<T>(arg:T):T{        // 使用T作为参数占位
  return arg
}
const result:number = echo(123)
const result:string = echo('123')
const result:boolean = echo(true)

参数是一个数组的时候,加泛型

function swap<T,U>(tuple:[T,U]):[U,T]{
   return [tuple[1],tuple[0]]
}
const result2 = swap(['string',123])
result2[1] // number
result2[0] // string

对函数使用泛型加约束

Eg:

function echoWithArr<T>(arg:T):T{
  console.log(arg.length)
  return arg
}
// 会报错,因为T可能没有length,如果给T加约束
function echoWithArr<T>(arg:T[]):T[]{
  console.log(arg.length)
  return arg
}
// 改造成了传T类型的数组,错误取消,但是如果想判断字符串的length呢,如果是对象中含有length呢,上面的改造就不能实现了,继续改造

interface IWithLength{
  length:number;
}
function echoWithLength<T extends IWithLength>(arg:T):T{
   console.log(arg.length)
   return arg
}
const str = echoWithLength('str')
const obj = echoWithLength({length:12,width:'12'})
const arr = echoWithLength([1,2,3])
// 以上都可以满足,问题解决

对类使用泛型约束

class Queue<T>{
  private data = [];
  push(item:T){
    return this.data.push(item)
  }
  pop():T{
    return this.data.shift()
  }
}
const queue = new Queue<number>();
queue.push(1)
const queue2 = new Queue<string>();
queue.push('1')

对接口加泛型

interface KeyPair<T,U>{
  key:T;
  value:U;
}
let kp1:KeyPair<number,string> = {key:123,value="str"}
let kp2:KeyPair<string,number> = {key:"str",value="123"}

对数组加泛型

let arr:number[] = [1,2,3]
let arr2:Array<number> = [1,2,3,4]
interface IPlus<T> {  // 描述了一个函数的类型
  {a:T,b:T}: T
}
function plus(a:number,b:number){
  return a+b;
}
function connect(a:string,b:string){
  return a+b;
}
const a:IPus<number> = plus;
const b:IPus<string> = plus;
  • 类型别名和断言as
// 别名 type aliases
function sum(x;number,y:number):number {
return x+y
} 
const sum2:(x;number,y:number)=>number = sum
// sum2 太长,用类型别名
type PlusType = (x;number,y:number)=>number
const sum2:PlusType = sum
// 断言 as 分别判断不同类型的不同处理方式
function sum(input:string | number) :number {
   const str = input as String;
   if(str.length){
     return str.length
   }else{
      const number = input as Number;
      return number.toString().length
   }
} 
=>
function sum(input:string | number) :number {
   if((<string>input).length){
     return (<string>input).length
   }else{
      return input.toString().length
   }
} 
  • 声明文件
jQuery('#f00');

使用一

declare var jQuery:(selector:string)=>any

一般单独放在一个文件jQuery.t.ts 中声明,以.d.ts结尾

tsconfig.json

{
  "include":["**/ *]
}

使用二

第三方库

查找第三方库地址

npm install --save @types/jquery


studytypescript地址