Typescript

ts的基本类型

1.布尔型:var a:boolean =false ,var a:Boolean=true

2.数值型:var a:number=2; var a :Number=2;var b:bigint 数值中的大整形 ;c=0xff 十六进制中的数值型

3.字符型 var a :string=''a" ;var b:string='b' ;var c=String=`c`

4.undefined : var a: undefined=undefined;  

5.null类型 :var a:null=null  ,null只能赋给对象,其他的用undefined

例子:var obj:object|null={a:1,b:2};//目的是清理对象,被垃圾回收车回收

obj =null

6.symbol类型:var a:symbol=symblo('a')

7.type类型 (或者):var a :undefined | number ; 等同于var a?:number 【只能在函数传参的时候用】,

例1:

 function fn(a?:number){
   }
    fn();

 例2

interface IC{
    name:"IC";
    a:number;
    b:number;
}
interface ID{
    name:"ID";
    c:string;
    d:string;
}
interface IE{
    name:"IE";
    e:boolean;
    f:boolean;
}
type IF=IC | ID | IE;
function getsum(s:IF){  
//这里s是一个对象于传入函数参数// var s:IE={name:"IE",e:true,f:true},s对象中有name属性
//通过Switch 对象的name,再进行操作
    switch(s.name){
        case "IC":
            break;
        case "ID":
            break;
        case "IE":
            break;
    }
}
//给了三个接口,每个接口都有一个name属性,并且IF是type类型,在函数调用的

7.1 obj?.a 当obj存在的时候才会调用

8.数组类型:var arr:number[]=[1,2,3] var arr:Array<number>=[1,2,3]

var arr :Array <number|string>=[1,2,'aa',3]

8.1二维数组 var arr :Array<Array<number>>=[ [1,2,3],[4,5,6] ]

9.元组类型 var arr:[string,number,boolean]=['aa',1,true]

10.枚举类型;enum COLOR{RED,YEELO,GREEN}  一般定义于类型常量

                         console.log(COLOR.RED) //0

                     enmu COLOR{RED='red',YELLOW='yellow',GREEN='green'}

                  console.log(COLOR.RED)  //'red'

11.type类型  一般用于选项

type COLOR='red'|'yellow'|'green'

var c:COLOR:'red' //此时'red'|'yellow'|'green'这三个选项会弹出,要是写这三个以外的就会报错

12.any类型(定义了any类型就会任意类型都会使用)禁止使用

  例子

var a :any="a"
a=1;a=true

13.不用返回值 void;var a :void

函数

14.function fn():number{ return 5} //返回值是数值型

15.function fn():never{ throw new Error("aa");}

回调函数中也需要写类型

例如:

fns(function(a:number,b:number):number
{
    return a+b;
})
//fns是回调函数
function fns(callback:(a:number,b:number)=>number){ //第三个参数是回调函数返回的类型
    callback(3,4);
}

15.declare:类型:为了声明,实现ball.d.ts,可以在写的时候会提示你所属于的类或者接口中有哪些类型,再调用的时候会出现提示

函数中的参数: 先必填参数,再默认参数,最后是缺省参数

                         a:number必填参数    b:number=2 默认参数      c?:number 缺省参数       

                          ...arg:Array<number>剩余参数

                            this:void  this参数必须写在函数参数最前面

例子:

function fn(this:void,a:number,c:number=2,b?:number,...arg:Array<number>):number
{
    return a;
}

对象

16.var o :object={a:1,b;2}          var o :object=new Object({a:1,b:2})

    o.c=3//不允许添加      o.a=10//不能修改    delect.o.a //不允许删除    console.log(o.a)不允许查看

用处:在函数中的参数,还有接口中

例如:

function fn(obj:object):void
{
    console.log(obj.a)//还是不能查看
}
fn({a:1,b:2});
function fn({id,name,info} //前面相当于解构obj:{id:number,name:string,info:string}//这是对象属性值的类型):{id:number,name:string}//这里是函数返回的类型
{
    return {id,name};
}

fn({id:10101,name:"ajas",info:"asdkajsd"});

可以增删改查对象的方法:

1.只可以查看与修改:

var obj:{a:number,b:number}={a:1,b:2}

  obj.a=10,obj.b=20 ;console.log(obj.a)//不会报错,若是添加,删除就会报错

2.增删改查

var obj:{[key:string]:number|string|boolean}={a:1,b:2}
obj.c='a' delect obj.a  obj.c=4;console.log(obj.b)
//此时都不会报错

例子:

var obj:{a:number,b?:number,c?:number}={a:1,b:2};
//可以修改a,b,c,但不能添加,也不能删除a

在类中

class B{
    private bindHandler:(e:MouseEvent)=>void;
    constructor(){
        this.bindHandler=(e:MouseEvent)=>this.clickhandler(e);
        document.addEventListener("click",this.bindHandler);
    }
    private clickhandler(this:B,e:MouseEvent):void  //这里的this指向的B,所以是B类型,e:是MouseEvent类型
    {
        this.play();
        document.removeEventListener("click",this.bindHandler);
    }
    private play():void
    {

    }
}

断言  as

例一:

    clickHandler(e:MouseEvent):void
    {
        if((e.target as HTMLElement).nodeName!=="DIV") return;
    }

例子2:

export default class Box{
    elem:HTMLDivElement;
    constructor(){
        this.elem=document.createElement("div");
        this.elem.addEventListener("click",e=>this.clickHandler(e));
    }
    appenTo(parent:string|HTMLElement){
        if(typeof parent==="string") parent=document.querySelector(parent) as HTMLElement;
//因为不知道parent是什么类型就断言他是HTMLElement类型
        if(parent) parent.appendChild(this.elem);

TS中类的方法

1.private:私有的,只能自己使用,继承自己的跟实例化的不可以用用private标记的方法

2.protected:受保护的,自己跟继承自己的子类都可以调用的方法,但是在实例化对象中不可以       使 用

3.public:共有的,都可以使用

4.readonly:只读属性,只能写在构造函数的参数中

例如:

export default class Ball extends Box{
    constructor(readonly ab:number){//ab 参数只能读取,不能修改
        super(ab);}}
interface IObj{
    readonly a:number;
    b:number;
}

var o:IObj={a:1,b:2};
console.log(o.a);
o.a=10;//会报错,因为a是只读属性

abstract  抽象类  

export default abstract class Base{
    constructor(){

    }
     public abstract update():void;
     protected run():void
     {
         console.log("play");
     }
}

在抽象类中的抽象对象,可以在继承的子类中,进行对父类的抽象方法进行修改,添加属性,在子类中不能用super()调用

import Base from "./Base";
export default class Rect extends Base{
    constructor(){
        super();
    }
    protected run(): void {
    }
    public update(): void {
        // 因为update继承时,Base类中对于update方法修饰为抽象方法,因此不可使用super.update()实现父类方法
        console.log("bbb");
    }
}

接口 interface

实现对象的接口

1.1只实现查改

interface IObj={
 a:number,
 b:number
}
var obj:IObj={a:1,b:2}//只能进行查与改

2.实现增删改查

interface IObj={
[key:string]:number|string|boolean
}
var obj:IObj={a:1,b:2}//这时可以增删改查

函数中的接口

例一

var fn:(a:number,b:number)=>number=function(a:number,b:number):number
{
    return a+b;
}

fn(4,6);

function fn(a:number,b:number):number
{
    return a+b;
}

fn(4,6);

两者的区别是相当于1. function fn(){}与  var fn=function(){}  2.第一个可以传接口

1.函数接口写法

interface IFn={
(a:number,b:number)
return  number
}
var fn:IFn=function(a:number,b:number):number{
return a+b
}

可索引类型

interface IArray{
[index:number]:number
}
var arr :IArray=[1,2,3,4]
console.log(arr[0])//可以通过索引拿到arr的值,
//注意这里arr不是数组类型,不能用数组的方法

var o:IArray={};
o[1]=10;
o[0]=20;
console.log(o);

类接口

注意:类通过implements去实现接口,类中的属性数量必须与接口的数量对应,不能在接口中定义了,但是在类中不写,但是可以添加自己的属性,属性也要对应,类中的属性必须是public,接口和抽象类都不允许实例化,原因是其内部只有属性名和方法名,并没有实际内容

接口与继承的区别

1.类继承的过程中只能实现一个父类的继承,单链性,继承会将所有实现方法及实现内容全部继承

2.同一个类可以实现多个接口。接口中不实现属性值和具体方法内容

例子

interface IA{
 a:number;  //不能有私有
play():void
}
interface IB{
 b:string;
run():void
}
interface IC{
 c:number;
jump():void
}
class A implements IA ,IB{   //通过implements实现接口
  public a:number=2           //接口里有多少属性就要全部写出,并且全部必须是public
  public:play():void{
  console.log('aaa')
public b:string='3'
  public:run():void{
  console.log('bbb')
}
}

class B implements IA,IC{
 public  b:string='w'  //这个接口中没有可以自己添加
    public a:number=20;
    public c:number=30;
    public play(): void {
        console.log("bbb")
    }
    public jump(): void {
        console.log("ccc")
    }
}

var a:A=new A()  注意这里实例化的a是A类型
var b:B=new B()
var arr:Array<IA>=[];  
//把实例化对象存到数组中,条件是必须实现了IA方法,
//要是没有实现IA将存不进去,会吧实例化的所有属性都存进去
arr.push(a);
arr.push(b);

在抽象类中不能实例化案例

interface HTMLDivElement_1{
    // style:CSSStyleDeclaration,
    width:number,
    onclick:(e:MouseEvent)=>void,
}

function createElement(type:string):HTMLDivElement_1
{
    var elem:HTMLDivElement_1={         //elem相当于一个对象
        width:1,
        onclick:function(e:MouseEvent){

        }
    }
    return elem;
}

var o:HTMLDivElement_1=createElement("div");
var o=new HTMLDivElement_1()//不可以,这样会报错

构造函数 

例子

interface IA{
new (a:number,b:number):IUpdate  //构造函数的接口 ,所以B类就是IA接口这个类型
}
interface IUpdate{   //构造函数中有什么方法,可以进行分类
    update():void

class B implements IUpdate{
    constructor(a:number,b:number){ 

    }
    public update(): void {
            console.log("aa")
    }
}
class C implements IUpdate{
    constructor(a:number,b:number){

    }
    public update(): void {
        console.log("bb")
    }
}
function createB(className:IA):IUpdate
{
    var b:IUpdate=new className(4,5);
//这里b就是Iupdata类型,因为再new构造函数的接口返回的就是IUpdate类型
    console.log(b);
    return b;
}
createB(B);  //这里相当于用一个函数,用classB来实例化b
createB(C);  //这里相当于用一个函数,用classC来实例化b

用泛型解决

function fn<T>(className:{new ():T}){
    console.log(className);
} 
fn<Ball>(Ball)
fn<Box>(Box)

接口继承类 


class B{
    public a:number=1;
    // private b:number=2; //接口继承类,不能有私有的存在
    public play():void
    {

    }
}

interface IA extends B{
    c:number;
}

class C implements IA{
    public a: number=1;
    public c: number=2;
     b:number=3;
    public play(): void {
        
    }
}

泛型 

通过泛型实现接口

1.类中的泛型接口

export interface IA <T>{  //这里T就是泛型
  a:T
}

在用的时候

import IA FROM './'
class B implements IA<number>{  
public  a: number =1
}

1.2反类型,在实例化传参的时候用

//定义一个泛类型,注意static静态属性不能给泛类型,因为静态只能自己使用,是用RECT.(点)的,不是new的
class RECT <T>{
 public a:<T>
constructor(_a){
  this.a =_a
}

}
//实例化的时候

var rect RECT:<number>=new  RECT(1)

1.3 泛型继承类  :注意不能实现接口,因为接口不可以实例化

fn<T extends Box>(o:T){}

2.对象中的泛型接口

interface IB<T,U>{
  a:T,
  b:u
}

在使用的时候
var o:IB<number,string>={a:1,b:"a"};
var o1:IB<number,number>={a:1,b:2};
var o2:IB<string,boolean>={a:"a",b:true};
var o3:IB<Array<string>,Array<number>>={a:["a","b"],b:[1,2,3]};

//这时候属性值的类型就可以直接自己定义什么类型,不用直接写死

//之前的接口写法
interface IObj={
 a:number,
 b:number
}          //这样在使用接口的时候只能是number类型的
var obj:IObj={a:1,b:2}//只能进行查与改

3.函数中的参数的泛型

function fn<T>(a:T){
}
var b:Box=new Box();
fn<Box>(b);  //此时参数b就是Box类型

var c:Ball=new Ball();
fn<Ball>(c);  //此时参数b就是Ball类型

混合交叉类型   

理解:就是你不确定他返回什么类型就用交叉类型&

例子:

function minxi<T,U>(a:T,b:U):T & U //因为返回的是两种类型
{
    var result=<T & U>{};
    for(var key in a){
        (<any>result)[key]=a[key]; //使用any因为刚开始你不知道result是什么类型
    }
    for(var key1 in b){
        (<any>result)[key1]=b[key1];//使用any因为刚开始你不知道result是什么类型
    }
    return result;
}
interface IC{
    name:"IC";
    a:number;
    b:number;
}
interface ID{
    name:"ID";
    c:string;
    d:string;
}

//调用  var c:IC & ID=minxi<IC,ID>(o,o1);

装饰器

function f(){
    return function(target:C,key:string){  //这里的target是类,key是类里的方法
        // console.log(target,key);
        console.log(key);
         target.method(); //不需要调用就会执行C类里面的method()方法
    }
}
class C{
    @f()   //z再实例化C类的时候会先执行f这个函数,注意@f不能写在函数内部
    play(){
    }
    @f()
    method() {
        console.log("ab")
    }
 }
var c:C=new C();
    // c.method();

通过单线程与中介实现解耦 

理解:解耦的目的是拆分两个关联的类的代码,通过中介来把这两个代码关联起来,当你删除其中一个另一个不会报错,而这个中介就是通过单线程实现

一.实现单线程方法一

问题:在触发Box 中的play方法的时候就会执行ball中的run方法

class Box{
    private a:number=1;
    constructor(){

    }
    public play(){
        this.a++;
        ViewModel.instance.data=this.a;
    }
}


---------------------------------------------------
class Ball{
    constructor(){
        ViewModel.instance.addEventListener("change",e=>this.run(e));
    }
    private run(e:Emitter){
        console.log(e.a);
    }
}
 


------------------------------------------------
import Emitter from "./Emitter";
import EmitterTarget from "./EmitterTarget";
export default class ViewModel extends EmitterTarget{
    private static _instance:ViewModel;
    public b:number=1;
    private _data?:number;
    private constructor(){
        super();
    }
    public static get instance():ViewModel{
        return ViewModel._instance || (ViewModel._instance=new ViewModel());
    }
    public set data(value:number){
        this._data=value;
        var evt=new Emitter("change");
        evt.a=value;
        this.dispatchEvent(evt);
    }
    public get data():number
    {
        if(!this._data) this._data=0;
        return this._data;
    }
}
//此时创建了一个单例ViewModel.instance,因为ViewModel.instance就是相当于ViewModel的实例化对象,所以就可以调用里面的public方法,再任何时候,只要引入了这个类,就可以使用ViewModel.instance.data,
   //所以在BOX类中的play()方法中改变ViewModel.instance.data的值,然而在ViewModel.instance.data中的set方法在赋值的时候就会触发,所以就可以在set方法中抛发事件,并且在ball类中监听事件,事件函数是run,所以在在执行BOX类中的play方法的时候就会执行Ball中的run方法

思路:1.此时创建了一个单例ViewModel.instance,因为ViewModel.instance就是相当于ViewModel              的实例化对象,所以就可以调用里面的public方法,再任何时候,只要引入了这个类,就                       可以使用ViewModel.instance.data,
   2.所以在BOX类中的play()方法中改变ViewModel.instance.data的值,然而在ViewModel.instance.data中的set方法在赋值的时候就会触发,所以就可以在set方法中抛发事件,并且在ball类中监听事件,事件函数是run,所以在在执行BOX类中的play方法的时候就会执行Ball中的run方法

二.单例实现二

思路:此时 MainModel.getInstance()就相当于实例化的MainModel对象,因为a是公共的所以,在认可地方都可以调用MainModel.getInstance().a,因此可以通过a的改变状态,来抛发事件,别的类中监听事件,与例子一的思路一样,就是实现单例的方法不一样,这个也需要设置get,set

export default class MainModel{
    private static _instance:MainModel;
    public a:number=1;
    private constructor() {
    }
    public static getInstance():MainModel
    {
        if(!MainModel._instance)MainModel._instance=new MainModel();
        return MainModel._instance;
    }
}
此时 MainModel.getInstance()就相当于实例化的MainModel对象,因为a是公共的所以,在认可地方都可以调用MainModel.getInstance().a,因此可以通过a的改变状态,来抛发事件,别的类中监听事件,与例子一的思路一样,就是实现单例的方法不一样,这个也需要设置get,set

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值