typescript学习总结

typescript学习总结

qq学习讨论群:910316886

https://blog.csdn.net/m0_61044901/article/details/125274523

<!-- 
    安装: npm i -g typescript
    tsc -v (查看typescript版本)
  c盘用户 下去删除.npmrc文件
npm config set registry " https://registry.npm.taobao.org 
将ts编译为js,在终端输入命令,tsc hello.ts 执行js代码:在终端输入命令,node hello.js --> <!-- 简化执行步骤:

           # 初始化package.json 文件
           npm init -y

           # 局部安装 ts-node-dev typescript 依赖
           npm install ts-node-dev typescript

           # 在package.json 中的scripts中添加脚本
           "start": "ts-node-dev --respawn --transpile-only ./src"

             # 在终端中就可以使用npm start 启动项目
             npm start

    npm i -g ts-node
    ts-node hello.ts
-->



类型推断
let b=100;
b =''  //报错,只能是number类型,不能赋其他类型的值
any和unknown用法一样
<!--
    数组类型的两种写法
    let numbers:number[]=[1,2,3]
    let numbers2:Array<number>=[2,3,45,5]
    let strings:Array<string>=['a','b','c']
    let b:boolen[]=[false,true,false]

    既有数组又有字符串的类型(联合类型:由两个或多个类型组成的类型)
    let arr:(number|string)[]=[1,'a',3,'b'];
 -->

 <!-- 
    类型别名
    CustomArray这个是自己定义的任意合法的变量名
    创建类型别名后,直接使用该类型别名作为变量的类型注释即可
    type CustomArray = (number|string)[]
    let arr1:CustomArray=[1,'a',2,'ggg']
    let arr2:CustomArray=[3,'o',9,'sddsad']
  -->

  <!-- 
    函数类型:函数参数和返回值的类型
    为函数指定类型的两种方式:
        1 单独指定参数,返回值的类型  
            function add(num1:number,num2:number):number{
                return num1+num2;
            }
            add(1,2); //必须传参数
        2 同时指定参数、返回值的类型(只适用于函数表达式)
            const add:(num1:number,num2:number)=>number=(num1,num2)=>{
                return num1+num2;
            }
        3 如果函数没有返回值,那么,函数返回值的类型为:void
            function greet(name:string):void{
                console.log('hello',name)
            }
            greet('susu')
        4  可选参数:在可传可不传的参数名称后面加?(问号)
            可选参数只能出现在参数列表的最后,也就是说可选参数后面不能再出现必选参数
            function mySlice(start?:number,end?:number):void{
                console.log('起始索引:',start,'结束索引:',end)
            }
            mySlice(1,2)
            mySlice(1)
            mySlice()
   -->

   <!-- 
        对象类型
        let person:{name:string;age:number;sayHi():void}={
            name:'susu',
            age:18,
            sayHi(){}
        }
        sayHi():void是一个方法,表示没有返回值;
        换行,可以把分号去掉
          let person:{
                name:string
                age:number
                sayHi():void
            }={
                name:'susu',
                age:18,
                sayHi(){}
            }
    -->

    <!--
        接口
        当一个对象类型被多次使用时,一般会使用接口(interface)来描述对象的类型,达到复用的目的。
        1 使用interface关键字来声明接口
        2 接口名称(可以是任意合法的变量名称)
        3 声明接口后,直接使用接口名称作为变量的类型
        4 因为每一行只有一个属性类型,因此,属性类型后没有;(分号)

        interface IPerson{
            name:string
            age:number
            sayHi():void
        }
        let person:IPerson={
            name:'susu',
            age:16,
            sayHi(){}
        }
    -->

    <!-- 
        interface(接口)和type(类型别名)的对比
        相同点:都可以给对象指定类型
        不同点:
            接口:只能为对象指定类型
            类型别名,不仅可以为对象指定类型,实际上可以为任意类型指定别名
        
        interface IPerson{
            name:string
            age:number
            sayHai():void
        }

        type IPerson={
            name:string
            age:number
            sayHi():void
        }
     -->

     <!-- 
        extends
        interface Point2D {x:number,y:number}
        interface Point3D extends Point2D {z:number}
    -->

    <!-- 
        元组:
            它确切的知道包含多少个元素,以及特定索引对应的类型
        let position:[number,number]=[39.54,116.23]

      {
        //限制每一个元素的类型,只能有2个元素
        let a: [string, number];
        a = ['hello',20];
      }

     -->

     <!-- 
        类型推论:
        声明变量并立即初始化值,此时,可以省略类型注释
        能省略类型注释的地方就省略
        决定函数返回值也可以进行推论

        类型断言,通过as关键字指定一个更加具体的类型
        console.dir($0)打印结果的最后就可以看到元素的类型
      -->

      <!-- 
        字面量类型

        {
          //{}表示代码块
          //字面量限制取值范围
          let color :'red'|'green'|'blue';

          color = 'red';
          color = 'green';
          color = 'blue';

          let num:1|2|3;
          num = 2;
        }


        一般用在一组可明确的可选值类型
        function changeDirection(direction:'up'|'down'| 'left'| 'right'){
        }
        changeDirection('up')
    -->

    <!-- 
        枚举
        enum Direction {Up,Down,Left,Right}  默认0,1,2,3

        function changeDirection(direction:Direction){
            console.log(direction)
        }
        changeDirection(Direction.Up)

        枚举成员初始化值 
            enum Direction {Up=10,Down,Left,Right} 10,11,,12,13
            enum Direction {Up=10,Down=12,Left=14,Right=16}
            enum Direction {Up='UP',Down='DOWN',Left='LEFT',Right='RIGHT'}
     -->

     <!-- 
        class类
        class Person{
            age:number,
            gender='男'
            constructor(age:number,gender:string) {//构造函数不需要返回值
                this.age = age
                this.gender = gender
            }
        }
        const p =  new Person(15,'女')
        console.log( p.age, p.gender)  
      -->
    <!-- 
        interface Singble{
            sing():void
            name:sting
        }

        class Person implements Singable{
            name='susu'
            sing(){
                console.log('哈哈哈')
            }
        }

        解释:implements实现接口
            1 通过implements 关键字让class实现接口
            2 Person类实现接口singable意味着,Person类中必须提供Singable接口中的方法和属性
     -->

     <!-- 
        可见性修饰符
        1 public
        2 protected 仅对其声明所在类和子类中可见
        3 private 表示私有的,只在当前类中可见;对其实例对象以及子类也是不可见的
        4 readonly 表示只读,用来防止在构造函数之外对属性进行赋值,也不可以用于方法
            (需要指定类型,不然就变成字面量了;接口和普通的对象中也可以使用readonly;只读不可赋值)
    -->
      
    <!-- 
    类和接口的兼容性:成员多的可以复制给成员少的
    函数兼容性(参数少的可以赋值给多的)
    -->

    <!-- 
        交叉类型:组合多个类型为一个类型
        interface Person {name:string}
        interface Contact {phone:string}
        type PersonDetail = Person & Contact
        let obj:PersonDetail={
            name:'jack',
            phone:'1333'
        }    
    -->

  <!-- 
    泛型
     泛型在保证类型安全的同时,可以让函数和不同类型的数据一起使用
    function id<Type>(value:Type):Type{return value}
        const num=id<number>(10)
        也可以简写成   const num=id(10)
    -->
    <!-- 
        泛型类
        class GenericNumber<Numype>{
            defaultValue:NumType
            add:(x:NumType,y:NumType)=>NumType
        }
        const myNum = new GenericNumber<number>()
            myNum.defaultValue = 0
     -->

     <!-- 
        泛型工具类型
        1 Partial创建一个新的类型,并且属性是可选的
            interface Props{
                id:string
                children:number[]
            }
            type PartialProps = Partial<Props>
            
            let p1:Props={
                id:'',
                children:[1]
            }
            let PartialProps{
                id:''
            }
        2 Readonly 所有属性都是可读的
            interface Props{
                id:string
                children:number[]
            }
            type PartialProps = Readonly<Props>
            
            let p1:PartialProps{
                id:'222',
                children:[1,2,3]
            }
            p1.id='2'//报错
        3 Pick Pick<Type,keys>从Type中选择一个属性来构造新类型
            interface Props{
                id:string
                children:number[],
                title:string
            }
            type PickProps = Pick<Props,'id'|'title'>
        
        4 Record<Key,Type>构造一个对象类型,属性键为keys,属性类型为Type
            type RecordObj=Record<'a'|'b'|'c',string[]>
            let obj:RecordObj={
                a:['1'],
                b:['2'],
                c:['3']
            }
      -->

      <!-- 
        索引签名类型
        interface AnyObject{
            [key:string]:number  key是一个占位符,可以换成任意合法的变量名
        }

        let obj:AnyObject{
            a:1,
            b:2,
            c:3
        }

        interface MyArray<Type>{
            [n:number]:Type
        }
        let arr:MyArray<number>=[1,2,3,4]
    -->
       
    <!-- 
        映射类型:基于旧类型,创建新类型(对象类型)
        type PropKeys='x'|'y'|'z'
        type Type1 = {x:number,y:number,z:number}
        type Type2 = {[key in PropKeys]:number}
        type Type3 = {[key in keyof Type1]:number}

        索引查询类型
        type Props = {x:number,y:number,z:number}
        type Prop = Props['x']
        type Prop = Props['x'|'y']
        type Prop = Props[keyof Props]  拿到所有索引
     -->

     <!-- 
        类型声明文件
        为已存在的js库,提供类型信息
        包含内置的ts类型声明文件,库自带的类型声明文件以及github中DefinitedTyped
        TS官方文档中提供了一个页面,用来查询@types/*库的类型,在工具里
    
        declare关键字:用于类型声明,为其它地方,已存在的变量声明类型,而不是创建一个新的变量
    -->

    <!-- 
        type a = 'a'|'b'|'c'
        type b = 'b'|'c'
        //剔除
        type Atype = Exclude<a,b>
        let aDate:Atype='a'
        //包含
        type Btype = Extract<a,b>
        let aDate:Atype='b' //或者c
     -->

     <!-- 
        命名空间:内部模块,主要用于组织代码,避免命名冲突
       export namespace A{
            interface Animal{
                name:string
            }

            export class Dog implements Animal{
                name:string
                constructor(theName:string){
                    this.name = theName
                }
                eat(){
                    console.log(`${this.name}在跑。`)
                }
            }
        }
        export namespace B{
            interface Animal{
                name:string
            }

            export class Cat implements Animal{
                name:string
                constructor(theName:string){
                    this.name = theName
                }
                eat(){
                    console.log(`${this.name}在玩耍。`)
                }
            }
        }

        let dog= new A.Dog('小狗')
        dog.eat()
        let cat =new B.Cat('小猫')
        cat.eat();

        import {A} from '文件名'
      -->

      <!--
        类装饰器
        方法一:普通装饰器,没办法传参
        function logClass(params:any){
            console.log(params)
            params.prototype.apiUrl = '动态扩展属性'
            params.prototype.run=function(){
                console.log('我在跑步')
            }
        }

        @logClass //普通装饰器,没办法传参
        class HttpClint{
            constructor(){

            }
            
            getDate(){
                console.log('获取数据')
            }
        }

        let http = new HttpClint()
        http.run()

        方法二:类装饰器,可传参
        function logClass(params:any){
            return function(traget:any){
                console.log(target)
                console.log(params)
                traget.prototype.apiUrl = params
            }
        }

        @logClass('hello')
        class HttpClint{
            constructor(){

            }
            
            getDate(){
                console.log('获取数据')
            }
        }

        let http2 = new HttpClint();
        console.log(http.apiUrl)

        修改类中的属性和方法

        function logClass(target:any){
            console.log(target)
            return class extends target{
                apiUrl:any='我是修改后的数据'
                getDate(){
                    this.apiUrl=this.apiUrl+'......'
                    console.log(this.apiUrl)
                }
            }
        }

        function logProperty(params:any){
            return function(target:any,attr:any){
                console.log(target,attr)
                target.attr = params
            }
        }

        @logClass('hello')
        class HttpClint{
            @logProperty('http://itying.com')
            public apiUrl:string |undefined;
            constructor(){
                this.apiUrl = '我是构造函数里的apiUrl'
            }
            
            getDate(){
                console.log(this.apiUrl)
            }
        }

        let http2 = new HttpClint();
        console.log(http2.apiUrl)
        htttp2.getDate()
        -->

        <!-- 
            ///<reference path='路径'>
                最外层的namesapce不能导出,不然会报错
         -->

         <!-- 
            infer关键字
          -->

          <!-- 
            bight与symbol
           -->

联合类型

{
let a : string|number|string[]|number[] = [1,4];
a = ['a', 'b', 'c', 'd', 'e'];
a = 1,2,3,4,5,6,7,8;
a = 'hello','hi';
}

 

类型断言

{
//类型转换
let a : unknown = 'hello world';
// let length =a.length //报错:unknown没有length,只要string有
let length1 =(a as string).length //给a转类型,用as装
let length2 =(<string>a).length //用泛型转变
console.log(length1,length2);
}

 

函数的参数

{
//普通参数
function a (x:boolean,y:boolean):void{}

//可选参数 ?代表可选 但可选不能放在第一个,必须放在必选参数之后
function b (x:number,y?:number){}

//默认参数
function c (x:number,y:number = 1000){}

//剩余参数
function d (x:number,y:number ,...args:number[]){
console.log(x,y,args);

}

a(true,false);

b(100);
b(7,23);

c(100);
c(100,100);

d(10,20,1,2,3,4);
}

 

 

TypeScript抽象类
1)什么时抽象类?

被abstract修饰的类,就是抽象类,抽象类又叫基类

2)为什么要有抽象类?

为了规定类中的一些属性和方法,在被继承的时候必须重写,所以被abstract修饰的方法和属性,在继承时必须重 写,分别叫做抽象类和抽象方法

3)抽象类的特点:

抽象类自身无法实例化,必须由子类(派生类)进行实例化

抽象类也可以拥有自己的抽象方法和属性

抽象类中的抽象方法和抽象属性必须被重写

{
    //被abstract修饰的类叫做抽象类
    //抽象类不能实例化(创建对象),只能作为基类(父类),派生类(子类)
    //只能被继承,继承的时候需要重写父类中的抽象属性和抽象方法
    //被abstract修饰的属性叫做抽象属性,不能直接赋值
    //被abstract修饰的方法叫做抽象方法,不能有方法体
    //抽象属性和属性方法不能有具体的实现
 
    //抽象类用来定义类的结果(属性,方法)
    abstract class Person {
        abstract name: string;
        abstract sayHi();
       
    }
 
    //继承抽象类
    class Student extends Person {
        name: string;
 
        constructor(name: string){
            super();
            this.name = name;
        }
 
        sayHi() {
            console.log('${this.name}:hi');
            
        }
    }
    const stu = new Student('chen');
}

  


 

posted @ 2022-12-03 01:47  web与webGL  阅读(53)  评论(0编辑  收藏  举报