TypeScript基础学习

TypeScript简介

  1. TypeScript是JavaScript的超集。
  2. 它对JS进行了扩展,向JS中引入了类型的概念,并添加了许多新的特性。
  3. TS代码需要通过编译器编译为JS,然后再交由JS解析器执行。
  4. TS完全兼容JS,换言之,任何的JS代码都可以直接当成JS使用。
  5. 相较于JS而言,TS拥有了静态类型,更加严格的语法,更强大的功能;TS可以在代码执行前就完成代码的检查,减小了运行时异常的出现的几率;TS代码可以编译为任意版本的JS代码,可有效解决不同JS运行环境的兼容问题;同样的功能,TS的代码量要大于JS,但由于TS的代码结构更加清晰,变量类型更加明确,在后期代码的维护中TS却远远胜于JS。

TypeScript 开发环境搭建

  1. 下载Node.js
    64位:https://nodejs.org/dist/v14.15.1/node-v14.15.1-x64.msi
    32位:https://nodejs.org/dist/v14.15.1/node-v14.15.1-x86.msi
  2. 安装Node.js
  3. 使用npm全局安装typescript
    进入命令行
    输入:npm i -g typescript
  4. 创建一个ts文件
  5. 使用tsc对ts文件进行编译
    进入命令行
    进入ts文件所在目录
    执行命令:tsc xxx.ts(执行后就可以将ts文件编译成js文件)

TS类型声明

  • 类型声明是TS非常重要的一个特点
  • 通过类型声明可以指定TS中变量(参数、形参)的类型
  • 指定类型后,当为变量赋值时,TS编译器会自动检查值是否符合类型声明,符合则赋值,否则报错
  • 简而言之,类型声明给变量设置了类型,使得变量只能存储某种类型的值
    在这里插入图片描述
    自动类型判断
  • TS拥有自动的类型判断机制
  • 当对变量的声明和赋值是同时进行的,TS编译器会自动判断变量的类型
  • 所以如果你的变量的声明和赋值时同时进行的,可以省略掉类型声明

TS类型

类型展示

类型例子描述
number1, -33, 2.5任意数字
string‘hi’, “hi”,‘hi’任意字符串
booleantrue、false布尔值true或false
字面量其本身限制变量的值就是该字面量的值
any*任意类型
unknown*未知类型的值(类型安全的any)
void空值(undefined)没有值(或undefined)(以函数为例就是没有返回值)
never没有值不能是任何值 (永远不会返回结果)
object{name:‘孙悟空’}任意的JS对象 (可以指定有哪些属性以及属性的类型)
array[1,2,3]任意JS数组
tuple[4,5]元素,TS新增类型,固定长度数组
enumenum{A, B}枚举,TS中新增类型

字面量类型

在这里插入图片描述

any

在这里插入图片描述

unknown

unknown表示未知类型的值,和any功能相似,但是比any安全
在这里插入图片描述
在这里插入图片描述

解决以上问题的办法:
在这里插入图片描述

在这里插入图片描述

never

在这里插入图片描述

object

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

可选值要放在最后一个位置上
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
枚举
在这里插入图片描述

类型断言

  • 有些情况下,变量的类型对于我们来说是很明确,但是TS编译器却并不清楚,此时,可以通过类型断言来告诉编译器变量的类型,断言有两种形式:
    第一种:采用as
let someValue: unknown = "this is a string";
let strLength: number = (someValue as string).length;

第二种:在前面加上指定的类型

let someValue: unknown = "this is a string";
let strLength: number = (<string>someValue).length;

面向对象

面向对象的理解

一切操作都要通过对象,也就是所谓的面向对象,那么对象到底是什么呢?这就要先说到程序是什么,计算机程序的本质就是对现实事物的抽象,抽象的反义词是具体,比如:照片是对一个具体的人的抽象,汽车模型是对具体汽车的抽象等等。程序也是对事物的抽象,在程序中我们可以表示一个人、一条狗、一把枪、一颗子弹等等所有的事物。一个事物到了程序中就变成了一个对象。

在程序中所有的对象都被分成了两个部分数据和功能,以人为例,人的姓名、性别、年龄、身高、体重等属于数据,人可以说话、走路、吃饭、睡觉这些属于人的功能。数据在对象中被成为属性,而功能就被称为方法。所以简而言之,在程序中一切皆是对象。

class 类

要想面向对象,操作对象,首先便要拥有对象,那么下一个问题就是如何创建对象。要创建对象,必须要先定义类,所谓的类可以理解为对象的模型,程序中可以根据类创建指定类型的对象,举例来说:可以通过Person类来创建人的对象,通过Dog类创建狗的对象,通过Car类来创建汽车的对象,不同的类可以用来创建不同的对象。
类简介.ts

class Person{
    /* 
    *  直接定义的属性是实例属性,需要通过对象的实例来访问
    *    const per = new Person()   per.age
    * 
    * 使用static开头的属性是静态属性(类属性),可以直接通过类来访问
    * Person.age
    * 
    * readonly开头的属性表示一个只读的属性,无法修改
    */
    name:string = '张三'
    age:number = 25
    // 只读
    static readonly sex:string = '男'
    sayHello(){
        console.log('你好')
    }
    // 静态方法(类方法)
    static sayHi(){
        console.log('static Hi')
    }

}
const per = new Person()
console.log(per)
// 访问实例属性和实例方法
console.log(per.name,per.age)
console.log(per.sayHello)
// 访问类属性和类方法
console.log(Person.sex)
console.log(Person.sayHi)

在这里插入图片描述

构造函数

class Dog{
    name :string;
    age:number;
    // constructor被称为构造函数,构造函数会在对象创建(实例化)时调用
    constructor(name:string,age:number){
        // 在实例方法中,this就表示当前的实例
        // 在构造函数中当前对象就是当前创建的那个对象
        // 可以通过this向新创建的对象中添加属性
        this.name = name
        this.age = age
    }
    bark(){
        console.log(this)
    }

}
// 创建多个实例对象,并且赋不同的值
// 构造函数带有形参,创建实例对象的时候就必须传参
const dog = new Dog('旺财',2)
dog.name ='橘子'   //修改dog实例的name属性
const dog1 = new Dog('旺福',5)
dog.bark();
dog1.bark();

在这里插入图片描述

继承和重写

  • 继承时面向对象中的又一个特性
  • 通过继承可以将其他类中的属性和方法引入到当前类中
  • 通过继承可以在不修改类的情况下完成对类的扩展
  • 发生继承时,如果子类中的方法会替换掉父类中的同名方法,这就称为方法的重写
class Animal{
        name:string;
        age:number;
        constructor(name:string,age:number){
            this.name = name
            this.age = age
        }
        sayHello(){
            console.log('动物在叫~~~~~')
        }
    }
    /* 
    *Dog extends Animal
    *  -此时,Animal类被称为父类,Dog类被称为子类
    *  -使用继承后,子类将会拥有父类的所有方法和属性
    *  -通过继承可以将多个子类中共有的代码写在一个父类中
    *    --如果希望子类拥有一些父类中没有的属性或方法,就直接添加在子类中
    *  ——如果在子类中添加了和父类相同的方法,则子类方法会覆盖掉父类的方法,这就叫方法重写
    */
    class Dog extends Animal{
        sayHello(){
            console.log('狗在叫')
        }
        dogSay(){
            console.log('汪汪汪')
        }
    
    }
    class Cat extends Animal{
        sayHello(){
            console.log('猫在叫')
        }
        catSay(){
            console.log('喵喵喵')
        }
    }
    const dog = new Dog('发财',2)
    const cat = new Cat('咪咪',1)
    dog.sayHello()
    cat.sayHello()
    console.log(dog,cat)

在这里插入图片描述

super

 class Animal{
        name:string;
        constructor(name:string){
            this.name = name
        }
        sayHello(){
            console.log('动物在叫~~~~~')
        }
    }
    class Dog extends Animal{
        age:number;
        /* 
        *  如果在子类中书写了构造函数,在子类构造函数中必须对父类的构造函数进行调用,利用super
        *(原因:子类中重写构造函数后,就会将父类中的构造函数覆盖掉,这样父类中的name属性就没有被初始化,就会报错)
         */
        constructor(name:string,age:number){
            super(name);
            this.age = age
        }
        sayHello(){
            super.sayHello();
        }
    
    }
    const dog = new Dog('发财',2)
    dog.sayHello()

在这里插入图片描述

抽象类

 /* 
    * 以abstract开头的类是抽象类
    *       抽象类和其他类区别不大,只是不能用来创建对象
    *       抽象类就是专门用来呗继承的类
    * 
    *    抽象类中可以添加抽象方法
     */
    abstract class Animal{
        name:string;
        constructor(name:string){
            this.name = name
        }
        //定义一个抽象方法,抽象方法使用abstract开头,没有方法体
        // 抽象方法只能定义在抽象类中,子类必须对抽象方法进行重写
        abstract sayHello():void;
    }
    class Dog extends Animal{
        age:number;
        constructor(name:string,age:number){
            super(name);
            this.age = age
        }
        sayHello(){
            console.log('汪汪汪')
        }
    
    }
    const dog = new Dog('发财',2)
    dog.sayHello()

接口

接口的作用类似于抽象类,不同点在于接口中的所有方法和属性都是没有实值的,换句话说接口中的所有方法都是抽象方法。接口主要负责定义一个类的结构,接口可以去限制一个对象的接口,对象只有包含接口中定义的所有属性和方法时才能匹配接口。同时,可以让一个类去实现接口,实现接口时类中要保护接口中的所有属性。

 /* 
    *  接口可以在定义类的时候去限制类的结构,
    *  接口中的所有属性都不能有实际的值
    *  接口只定义对象的结构,而不考虑实际值
    *     在接口中的所有方法都是抽象方法
     */
    interface Myinterface{
        name:string;
        sayHello():void;
    }
    // 定义类时,可以使类去实现一个接口,实现接口就是使类满足接口的需求
    class Animal implements Myinterface{
        name: string;
        constructor(name:string){
            this.name = name
        }
        sayHello(){
            console.log('大家好!!!!')
        }
    }

属性的封装

class Dog {
        /* 
        *  public修饰的属性可以在任意位置访问和修改(默认为public)  数据不安全
        *  private  私有属性,私有属性只能在类内部进行访问,子类中也不可以访问
        *    ——通过在类中添加getter  setter方法使得私有属性可以被外部访问
        *   protected  受保护的属性,可以在当前类以及当前类的子类中访问
         */
        private _name: string;
        private _age: number;
        constructor(name: string,age: number){
            this._name = name
            this._age = age
        }
 
        // TS中设置getter  setter的方式,这种方式设置完后访问的方式不变   dog.name    dog.name='大宝'(不用通过调用方法来访问和修改)
        // 注意变量名的书写方式
        get name(){
            return this._name
        }
        set name(value){
            this._name = value
        }
        get age(){
            return this._age
        }
        set age(value){
            if(value>=0){
                this._age = value
            }
        }

    }
    let dog = new Dog('旺福',2)
    console.log(dog.name)
    dog.name='大宝'
    console.log(dog.name)



    
    class C{
        // 可以直接将属性定义在构造函数中
        // 这种方式写构造函数,实例化对象传参后属性的复制就自动完成了
        constructor(public name:string,public age:number){
        }
    }
    let c = new C('ls',25)  
    console.log(c)

在这里插入图片描述

泛型

定义一个函数或类时,有些情况下无法确定其中要使用的具体类型(返回值、参数、属性的类型不能确定),此时泛型便能够发挥作用。

 /* 
    *  在定义函数或者是类的时候,如果遇到类型不明确就可以使用泛型
     */
    function fn<T>(sex:T):T{
        return sex
    }
    // 直接调用具有泛型的函数
    let result = fn('男') //不指定泛型,TS可以自动对类型进行判断,sex为字符串,函数返回类型也为字符串类型
    let result1 = fn<number>(1) //指定泛型,sex为number类型,函数返回类型也为number类型

    // 泛型可以同时指定多个
    function fn1<T,S>(a:T,b:S):T{
        console.log(b)
        return a
    }
    let result2 = fn1(1,2)
    let result3 = fn1<string,number>('hello',2)

    // 泛型也可以实现接口
    interface Inter{
        length:number
    }
    // T extends Inter  表示泛型T必须是Inter实现类(子类)
    function fn2<T extends Inter>(a:T){
        return a.length        
    }
    let result4 = fn2('zhangsan')
    let result5 = fn2({length:5,name:'ls'})

    // 类 使用泛型
    class MyClass<T>{
        name:T;
        constructor(name:T){
            this.name = name
        }
    }
    let my = new MyClass(10)
    let my1 = new MyClass('kj')
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值