李炎恢老师的TypeScript 视频笔记

typescript 安装

npm install -g typescript

检查是否安装 tsc -v

英文文档:https://www.typescriptlang.org/
中文(不长更新)www.tslang.cn

第一节:
新建01.ts 在里面写js语句 
tsc 01.ts 生成js文件  //编译typescript
node 01.js 运行js文件
以上步骤复杂 每次更改要tsc生成
配置vscode ,自动编译成js文件 。在项目根目录生产tsconfig.json : tsc --init
vscode菜单上, 终端-运行-tsc监视 --当前项目 。
完成后自动生成和打包js文件
可以在tsconfig.json中配置生成的目录地址 例如:outDir:"./dist"  放在dist文件夹中自动生成
学习时不生产直接执行ts。 node 01.ts
懒人方式不想打命令时 :安装code runner  。 启用后 右键运行runner 
会出现乱码,安装一个ts-node 。 npm i -g ts-node

第三节课:
let num :number =100;  //强制设置number类型
 如果有ts语法了 就必须用ts-node 01.ts 运行ts文件
不能强制转换类型,
数组内数据类型不同时 let arr:[number,string,boolean]
TS的特殊类型
1,any(任意值) 2、null(不存在的对象) 3、undefined(声明但未初始化赋值)
4、void(空值,无返回,不允许返回)

第四节:枚举类型(包裹相关的声明变量的一种方式。优势明显,代码优雅,提高了可读性)
enum weeks{
	one,two,tree,four
}
console.log(weeks['four']);或weeks.four
枚举类型可以强制更改里面的类型,但是后面也必须更改
weeks[0] 可以得到键名。 
const 可以变成常数枚举。
const enum Info{ name = 'mr.lee' ,age=20}

第五节: 联合类型和字面量
创建一个字面量类型  let myName : 'Mr.pan' = 'Mr.pan'  赋值和类型要一样, 例如性别只能是男或女
let gender : '男' | '女'  //这里是类型
gender = '男'  //这里是值
2. 联合类型 :使用| 表示多种类型的声明
let numPrStr : number | string
numOrStr  = 100  或 numOrStr = 'tomg' 都不会报错
方法中:  function info(other:number|string){ } //输出数字和字符串都可以

第六节:类型推断和断言
1. 什么是类型推断:如果不使用注解对变量进行类型定义,ts将自行对变量类型进行判断 。初始值是什么类型就固定成什么类型。
如果初始没有赋值 ,那么这个变量是any(任意类型)。输出最后赋值的值 。其他赋值不会报错
如果是方法 ,例如 function info(num1,num2) {}  //有报错,在tsconfig.json 文件中第28行 "strict:false",改成非严格模式。
正常来讲必须严格模式。 可以给参数家类型 info(num1:number,num2:string){}
2. 类型断言,在联合类型传参的时候,我们需要根据判断类型做响应的处理。
访问联合类型时,会检查所有类型都是否具备这个属性。如果 function info(info:number|string){ if(info.length) }
这里的info.length会报错,因为number没有长度属性。 此时;需要做类型的断言操作
断言类型有两种:
第一种 .<类型> 值;   //后续另一种类型也有这种符号,易混淆
第二种 .值as类型;  //推荐这种 ,jsx只支持这种
function info(info:number|string){ if((info as string).length){ return (info as string).length } else{ return info.toString().length}}  //先强行推断为字符串 .否则是数值就toString强行转换为字符出串。

第七节:类的使用
主要概念为:面向对象的思维、类、三大特性(封装,继承,多态)等知识点、
//创建类
class Person{
    name:string
    age:number
    constructor(name:string,age:number){
        this.name = name
        this.age =age
    }
    run():string{
        return this.name+'的年龄是:'+this.age
    }
}
let p =  new Person('Mrs.pan',30);
console.log(p.run())

第八节:类的继承
子类继承父类拥有父类的属性和方法,也可以再创建自己独有的特性;
ts支持多重继承,不支持多继承(一个子类继承多个父类)
//人类
class Person1{
    name:string
    age:number
    constructor(name:string,age:number){
        this.name = name
        this.age =age
    }
    run():string{
        return this.name+'的年龄是:'+this.age
    }
}
//子类 ,男的
class Man extends Person1{}
let m = new Man('男的',40);
console.log(m.run());
//子类,女的
class Woman extends Person1{
    //独有成员
    food:string='晚餐'
    //独有方法
   
    eat():string{
        return this.name +'吃'+this.food
    }
}
let w =new Woman('女士',44)
console.log(w.run())
console.log(w.eat());
//孙子类(多重继承) ,奶奶
class OldWoman extends Woman{}
let o = new OldWoman('老奶奶',80);
console.log(o.eat())

第九节:类方法的重写
类方法分为构造方法和普通方法。实现重写机制; 继承的子类互不干涉

//人类男
class Person2{
    name:string
    age:number
    constructor(name:string,age:number){
        this.name = name
        this.age =age
    }
    run():string{
        return this.name+'的年龄是:'+this.age
    }
}
//子类 ,男的
class Man2 extends Person2{

    heigt:string
    //构造函数重写
    constructor(name:string,age:number,heigt){
        //super关键字调用父类的构造方法
        super(name,age)
        this.heigt = heigt
    }
    //普通方法重新

    run():string{
        //普通方法采用super.方法调用
        return super.run()+',身高是'+this.heigt
    }
}
    
let m2 = new Man2('男的',40,1.90);
console.log(m2.run());
//子类,女的
class Woman2 extends Person2{}
let w2 =new Woman2('女士',44)
console.log(w2.run());
输出:
男的的年龄是:40,身高是1.9
女士的年龄是:44

第十节:类方法的重载
1.类方法的重载,即:方法相同但传参数不同从而执行不同的一种操作:
2.例如构造方法里,只能传一个参数,也可能只传递两个参数来实现不同效果;(参数相同但可选)
3.普通方法重载类似
//闭包解决重名
(function(){
    class Person{
        name:string
        age:number |undefined
        constructor(name:string,age?:number){
            this.name = name
            this.age =age
        }
        //?:是可选参数,参数会变成两个类型**和undefined
        run(flag?:boolean):string{
            if(flag ===false){
                return '无法显示'
            }
            if(this.age===undefined){
                return this.name+'的年龄保密'
            }  
            return this.name+'的年龄是:'+this.age
        }
    }
    let p1 = new Person('男的',40)
    console.log(p1.run(false));
    let p2 =new Person('女的')
    console.log(p2.run());
})()
输出:
无法显示
女的的年龄保密

第11节课:类成员的修饰符
1.不加修饰符情况下,成员字段和方法默认公共public完全可见的状态。
2.如果设置不同的可见性,一共三种方案:
(1) .public :默认设置,公有可见性;
(2) .protected :受保护的,自身和子类可访问;
(3) .private :私有的,只能自身访问;
3. 方法和构造方法也可以设置修饰符。
构造方法前加了protected 父类就不能实例化了 ,只有子类能够实例化。 如果没有子类,受保护和私有修饰符都可以

第12节课:类成员的存取器
1.成员字段访问
成员字段我们进行了封装保护,那么除了实例化的方案外,还怎么对外暴漏接口?
可以通过:setXXX()和getXXX()约定俗称的方法来实现对成员字段的取值赋值。
2.成员字段存取器
成员字段有专门的setter和getter方法来处理私有成员字段的取值赋值
class Person{
        // protected _name:string
        // protected _age:number 
        // constructor(_name:string,_age:number){
        //     this._name = _name
        //     this._age =_age
        // }
        //声明和构造简写方案,语法糖
        constructor(private _name:string,private _age:number){
            this._name =_name
            this._age =_age
        }
        //setter
        set name(name:string){
            this._name =name
        }
        //getter
        get name(){
            return this._name;
        }
        run():string{
            return this._name+'的年龄是:'+this._age
        }
    }
    let p = new Person('Mrs.v',30);
    console.log(p.run());
    p.name="Mr.lin"
    console.log(p.run());
    console.log(p.name);

第13节 :静态成员和方法
1. static 关键字用于声明静态成员和方法,这是一种不需要实例化的调用方式;
2. 一般用于各种工具类,方便直接调用使用,较为方便;
3.设置静态不能修改只读加readonly
class Person{
         name:string
         age:number 
         //设置静态并且只读不能修改  static readonly
         static readonly p:number =3.1415926
         constructor(name:string,age:number){
                this.name = name
                this.age =age
         }
         static getPi(){
             return '圆周率'+Person.p
         }
        //?:是可选参数,参数会变成两个类型**和undefined
        run():string{
            return this.name+'的年龄是:'+this.age
        }
    }
    console.log(Person.getPi())

第14节:抽象类大的使用
1.抽象类可以用于顶层制定和设计标准,让子类继承时去实现具体细节;
2.抽象类设计相关成员和方法,不用于具体使用,所以无法实例化;抽象类的关键字 abstract
3.抽象类定义了规范
//抽象类
    abstract class Person {
        constructor(protected name:string,protected age:number) {}
        //需要被子类实现的方法
        abstract run():string
    }
    class Man extends Person{
        constructor(name:string,age:number){
            super(name,age);
        }
        run():string{
            return this.name+'的真实年龄'+this.age
        }
    }
    let m = new Man('Mrs.pan',30);
    console.log(m.run());

第15节: 接口的访问
1.接口类类似于抽象类,只不过它更彻底,只提供标准却完全不实现细节;
2.具体表现在成员字段不可以赋值初始化,方法不可以实现。
不需要修饰符,都是public的
接口的实现:
//接口
    interface Person{
        name?:string
        age?:any
        run():string
    }
    interface Abc extends Person {
        def():string
    }
    //子类实现Person接口
    class Man implements Abc{
        name:string ='mo'
        age:number =90
        run(){
            return this.name+'的年龄是:'+this.age
        }
        def(){
            return 'string'
        }
    }
    let p = new Man();
    console.log(p.run());
输出:mo的年龄是:90
3.接口的成员和方法必须由子类实现,也可以设置为可选方案让子类自由实现  属性: name?:string  方法:run?():string
PS:这样实现的子类就不必强制去初始化或实现接口中的成员和方法了;
PS:继承只能继承一个父类,是接口实现支持实现多个接口;
PS:并且,接口还可以继承另一个接口,从而进行合并;

第16节:对象的接口类型
//接口类型
    interface Person{
        name:string
        age:number
        gander?:'男'|'女'|'未知'
        run():string
    }

    //对象字面量
    let man : Person ={
        name:'Mr.chen',
        age:30,
        gander:'男',
        run(){
            return this.name+'的年龄是:'+this.age+'岁'+ this.gander
        }
    }
    console.log(man.run())
 //接口的字段也可以设置任意属性,具体如下:
   interface Person{
	[arrtName:string]:any

   }
        //自定义任意类型
        [attrName:string]:any
PS:此时,对应的对象可以自由添加各种属性和类型;
PS:左边的string表示属性key的类型,只支持string和number;
PS:右边的any表示值value的类型,和普通类型限制一样;

第17节:泛型的变量
一.泛型变量
1.js和ES6没有泛型的概念,并且如果也没接触过包含后端的泛型。
2.那么理解泛型会比较困难,所以,这里花几节课把最简单那的了解下即可
在类型不明确的时候,我们可以使用泛型来解决这个问题,提高了灵活性
泛型最核心大的部分就是下面例子中的<T>,T就是泛型变量,将类型赋给它;
function info<T>(msg:T):T{
return msg  }
输出时1.可以自动推断 info(100) ; 返回100
如果要强制是string类型: info<string>('hello'); 返回string类型的hello
总结:泛型可以在调用的时候指定类型。 T是泛型变量 ,使用泛型代替any

第18节课: 泛型的数组
//普通数组
    let arr :number[]=[1,3,4]
    //不确定数组 T[]
    //泛型数组
    let arr1:Array<number>=[3,6,7]
    //不确定数组 Array[T]
    //    function setArr(value:any):Array<any>{
    //        return [value]
    //    }
    //    console.log(setArr('z'));
    //     function setArr<T>(value:T):Array<T>{
    //        let result :T[] = [value,value]
    //        console.log(result.length);
           
    //        return result
    //     }
    //     //调用时类型规定是number类型
    //    console.log(setArr<number>(9));

       //多个泛型灵活搭配
       function man<T,P>(name:T,age:P):[T,P]{
           return [name,age]
       }
       console.log(man<string,number>('Mr.pan',100))

第19节:泛型类型和接口
1.前面我们通过泛型变量的形式来存储调用方的类型从而进行检查;
2.而泛型也可以作为类型的方式存在,理解这点,先来接下函数的声明方式;

第20节:泛型类和约束
1.泛型也会有无法检查通过所有类型都具有同一个属性的问题,比如.length
2.使用泛型约束,继承接口
(function(){
    //泛型约束
    interface Ilength{
        length:number
    }
    function info<T extends Ilength>(msg:T):T{
        console.log(msg.length)
        return msg
    }
    console.log(info<string>('Mr.pan'))
})()

第21节:模块化
1.模块化可以用来复用和组织我们的diamagnetic,避免代码重名。也方便分离
2.模块化也就是export(导出)和important(引入),es6讲解过,这里不再赘述;
3.那么,我们使用模块来分离我们的接口和类,然后通过模块调用;

exprot导出 , import 导入
IPerson.ts
//接口类,限制成员字段和方法
export interface IPerson{
    name:string
    run():void
}
Person.ts
import { IPerson } from "./Iperson"
//实现接口类
export class Person implements IPerson{
    name:string = ''
    constructor(name:string){
       this.name =name
    }
    run(){
        console.log(this.name +'运行了..') 
    }
}
21.ts
import{Person} from './modules/Person'
let p =new Person('Mrs.Lan')
p.run();




















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值