TypeScript

Waxiangyu

TypeScript是一种由微软开发的自由和开源的编程语言。它是JavaScript的一个超集,而且本质上向这个语言添加了可选的静态类型和基于类的面向对象编程。最后还是会编译成javascript

typescript的好处

TypeScript的设计目的应该是解决JavaScript的“痛点”:弱类型和没有命名空间,导致很难模块化,不适合开发大型程序。ts是js的扩展,如 class / interface / module 等。这样会大大提升代码的可阅读性。另外它还提供了一些语法糖来帮助大家更方便地实践面向对象的编程。内部模块称为全名空间namespace,外部模块称为module.
type就是类型的意思,所以typescript是强类型的语言,它的类型检查可以避免很多不规范的写法。比较适用于大中型项目。es6语法跟他已经很相近了。比如classextends等。

tsconfig.json配置

{
  "compilerOptions": { //可以不写就是默认值
    "strict": false,
    "module": "es2015", //指定生成哪个模块代码。
    "moduleResolution": "node", //如何处理文档,node.js
    "target": "es5", //指定ECMA目标版本,默认为es3
    "allowJs": true, //包括.js,.jsx
    "experimentalDecorators": true,
    "allowSyntheticDefaultImports": true,
    "lib": [ //编译过程中可能引入的库文件列表
      "dom",
      "es5",
      "es2015.promise"
    ]
  },
  "include": [ //指定全局匹配列表。*包括.ts,.tsx,.d.ts
    "./src/**/*"
  ],
  "pretty": true
}

ts编译工具:ts-loader/@babel/preset-typescript
ts代码检查工具:eslint+typescript-eslint/babel-eslint
单元测试工具:ts-jest/babel-jest

基础类型(小写)

let isDone:boolean=false//布尔

let age:number=12//数字

let name:string="Bob"//字符串
let sentence:string=`hello ! my name is ${name}. 
I'll be ${age+1} years old.`;//字符串模板 
let u:undefined=undefined//undefined
let n:null=null//null,和undefined是其它类型的子类,其它类型的值可以赋值成undefined

let list:number[]=[1,2,3]==list:Array<number>=[1,2,3]//数组

let x:[string,number];
x=['hello',10]//元组Tuple

//never,永远不会有返回,抛错,死循环
let notSure:any=4//any类型,表示它可是一个任意类型的值
fuction warnUser():void{ 
    alert("this is a warn message!")
}//void空值,只能是null和undefined,或者是函数没有返回值

枚举enum


 //常数枚举第一个没有初始化的话默认为0,其后依次加1,反向映射
 const enum Directions {
   Up,//0
   Down,//1
   Left,//2
   Right//3
}

let directions = [Directions.Up, Directions.Down,Directions.Left, Directions.Right]
//var directions = [0, 1, 2, 3];

enum Color{
   Red,//0
   Blue,//1
   Green//2
}
let x:Color=Color.Red//0

enum Enum {
   A = 1,//常数枚举
   B = A * 2 //计算
}
declare enum Enum {//外部枚举,declare 声明全局
   A = 1,
   B,
   C = 2

}

接口interface

//同名的2个interface,使用时会进行合并
//可选属性,后面标识为?readonly只读属性,只能在刚刚创建的时候修改其值,创建后不能再改
interface squareConfig{
    readonly color:string,
    width?:number
}
    
//鸭子模型,一只鸟如果感觉它长的像鸭子,有鸭子的特征,那就可以把它当鸭子对待,声明属性少的兼容属性多的。

interface StrArray{
    [index:number]:string//[x:string]:any匹配多个异种属性
}
let chars:StrArray=['a','b','c']//字符串数组,带有索引为数字
//混合
interface Lib{
   ():void
   version:string
   do():void
}
//<type>,as type 类型断言
function getLib(){
   let lib:Lib(()=>{})as Lib
   lib.version='r';
   lib.do=()=>{}
   return lib
}
let lib1=getLib()
console.log(lib1.version)

class

//class声明了一个Greeter的类,有1个greeting的属性,1个构造函数,1个greet方法
class Greeter{
    greeting:string,
    constructor(message:string){
        this.greeting=message
    },
    greet(){
        return "hello,"+this.greeting
    }
}
let greeter=new Greeter("world")
//protected子类可用,不能实例化
//private不能实例化,不能继承
//抽象类只能被继承,不能实例化
abstract class Animal{
   eat(){
      console.log('eat')
      abstract sleep():void//抽象方法在父类中定义,子类中实现
   }
}
class Dog extends Animal{
   constructor(name:string){
      super()
      this.name=name
   }
   name:string
   sleep(){}
}
let dog=new Dog('e')
//多态
class Cat extends Animal{
   sleep(){}
}
let cat=new Cat()
let animals:Animal[]=[dog,cat]
animals.forEach(i=>i.sleeep())
//链式调用 
class Workfow{
   step1(){return 1}
   step2(){return 2}
}
new Workflow().step1().step2()
class MyFlow extends Workfow{
   next(){return this}
}
new MyFlow().next().step1().next().step2()
//接口与类
interface Human{//类的公有成员
   name:string
   eat():void
}
class Asian implements Human{
   constructor(name:string){
      this.name=name
   }
   name:string
   eat(){}
   sleep(){}
}
interface Man extends Human{//继承interface多个的话用,隔开
   run():void
}
class Auto{
   state=1
}
interface Sto extends Auto{}//接口继承类
class Bus extends Auto implements Sto{//类继承类用interface约束
    state=1
}

函数

//下面这3种声明函数的类型是一样的
let computer:(x:number,y:number)=>number;
interface Add{
    (x:number,y:number):number
}
type Add=(x:number,y:number)=>number
let add:Add=(a,b)=>a+b//类型别名

let myAdd:(baseValue:number,increment:number)=>number
=myAdd=function(x:number,y:number):number{return x+y}//函数的声明参数和返回值的类型
//参数里面写了几个,传的时候就应该是几个。而且类型必须相等。可在参数前+'?'表示可选参数


剩余参数

function buildName(firstName:string,...restOfName:string[]){
    return firstName+""+restofName.join("")
}
let buildNameFun:(fName:string,...rest:string[])=>string=buildName
//重载,最多匹配的放在最前端
function add2(...rest:number[]):number
function add2(...rest:string[]):string
function add2(...rest:any[]):any{
   let first=res[0]
   if(typeof first==='string'){
      return rest.join('')
   }
}

this

interface Card{
    suit:string,
    card:number
}
interface Deck{
    suits:string[];
    cards:number[];
    createCardPiker(this:Deck):()=>Card
}
let deck:Deck={
    suits:["hearts","spades","clubs","diamous"],
    cards:Array(52),
    createCardPiker:function(this:Deck){
        return ()=>{
            let pikerCard=Math.floor(Math.random()*52);
            let pidedSuit=Math.floor(pikerCard/13);
            return {suit:this.suits[pikedSuit],card:pikerCard%13}
        }
    }
}

泛型<T>

//规定参数是什么类型,返回值就应该是什么类型,可以把泛型想象成一个单独的函数,T就是泛型函数的参数
function identity<T>(arg: T): T {
    return arg;
}

function loggingIdentity<T>(arg: Array<T>): Array<T> {
    console.log(arg.length);  //数组类型
    return arg;
}
interface GenericIdentityFn<T> {//泛型接口
    (arg: T): T;
}
function identity<T>(arg: T): T {
    return arg;
}
let myIdentity: GenericIdentityFn<number> = identity;
//泛型约束,输入的必须有length属性
interface Length{
    length:number
}
function log<T extends Length>(value:T):T{//value必须是一个有length的参数
   console.log(value,value.length)
   return value
}
class GenericNumber<T> {//泛型类,直接后面加<>
    zeroValue: T;
    add: (x: T, y: T) => T;
}

let myGenericNumber = new GenericNumber<number>();
myGenericNumber.zeroValue = 0;
myGenericNumber.add = function(x, y) { return x + y; };

类型断言

let x = 3;//最基本的x会被推断为number类型

function createZoo(): Animal[] {
    return [new Rhino(), new Elephant(), new Snake()];
}
//这个例子里,最佳通用类型有4个候选者:Animal,Rhino,Elephant和Snake。 当然, Animal会被做为最佳通用类型。
//上下文归类通常包含函数的参数,赋值表达式的右边,类型断言,对象成员和数组字面量和返回值语句。 上下文类型也会做为最佳通用类型的候选类型。

enum Type{Strong,Week}
class Java{
   helloJava(){console.log('hello java')}
}
class JavaScript{
   helloJavaScript(){console.log('hello javascript')}
}
//3.类型保护函数,lang的值只能是java或者javascript,类型位词
function isJava(lang:Java|JavaScript):lang is Java{
   return (lang as Java).helloJava!==undefined
}
function getLanguage(type:Type){
   let lang=type===Type.Strong?new Java():new JavaScript()
   //因为lang是不确定的是java还是javascript,直接调用会报错,1.加类型断言
   //if((lang as Java).helloJava){
   //   (lang as Java).helloJava()
   //}else{
   //   (lang as JavaScript).helloJavaScript()
   //}
   //2.使用instanceof或typeof判断
   //if(lang instanceof Java){
   //   lang.helloJava()
   //}else{
   //   lang.helloJavaScript()
   //}
   //3.加类型保护函数
   if(isJava(lang)){
      lang.helloJava()
   }else{
      lang.helloJavaScript()
   }
   return lang
}
interface DogInterface{
   run():void
}
interface CatInterface{
   jump():void
}
let pet:DogInterface & CatInterface={//交叉,取所有类型的并集
   run(){},
   jump(){}
}
//联合类型:string|number表示或可以是string类型,也可以是number类型
let a:number|string='a'
let b:'a'|'b'|'c'//值只能是a,b,c
let c:1|2|3//值只能是1,2,3
interface Obj1{
  a:number
  b:string
}
let key:keyof Obj1//keyof T,key只能是Obj1的key
let value:Obj1['a']//T[K],  value的类型只是Obj1下a的类型number

//参数keys的值应该是obj的key的集合,返回obj里key值的value集合
function getValues<T,K extends keyof T>(obj:T,keys:K[]):T[K][]{
   return keys.map(key=>obj[key])
}
let obj2={a:1,b:2,c:3}
console.log(getValues(obj2,['a','b']))
//映射类型,内置函数
interface Obj3{
   a:string
   b:number
   c:boolean
}
type ReadonlyObj=Readonly<Obj3>
//变成只读,ts内置,内部实现
type Readonly<T>={
   readonly [P in keyof T]:T[P]
}

type PartialObj=Partial<Obj3>
//变成可选,内部实现
type Partial<T>={
   [P in keyof T]?:T[P]
}

type PickObj=Pick<Obj3,'a'|'b'>
//抽取子集,内部实现,{a:string,b:number}
type Pick<T,K extends keyof T>={
   [P in K]:T[P]
}

type RecordObj=Record<'x'|'y',Obj3>
//新的obj,内部实现,{x:Obj3,y:Obj3}
type Record<K extends keyof any,T>={
   [P in K]:T
}

//T extends U ? X : Y 三元运算如果T符合U里的类型,就是X类型,否则就是Y类型
//(A|B) extends U ? X : Y===(A extends U?X:Y)|(B extends U?X:Y)
type T6=Extract<'a'|'b'|'c','a'|'e'>
//a,提取同样的,type Extract<T,U> = T extends U ? T : never
type T7=Exclude<'a'|'b'|'c','a'|'e'>
//b|c,排除包含的,type Exclude<T,U>=T extends U ? never : T
type T8=NonNullable<'a'>
//a,type NonNullable<T>=T extends null|undefined ? never : T
type T9=ReturnType<()=>string>
//string,T可以被赋值给一个函数,参数和返回都是any,因为是any所以返回值infer待推断
//type RetrunType<T extends (...args:any)=>any>=T extends (...args:any)=>infer R ? R : any
//namespace,避免全局污染 ///<reference path='index.ts'/>引入其它命名空间文件使用
namespace Shape{
   export function square(x:number){//导出
      return x*x
   }
}
//实现
var Shape;
(function(Shape){
   var pi=Math.PI;
   function cricle(r){
      return pi*Math.pow(r,2)
   }
   Shape.cricle=cricle;
})(Shape||(Shape={}))
阅读 1.4k
628 声望
28 粉丝
0 条评论
628 声望
28 粉丝
文章目录
宣传栏