TS学习与实践

文章目录

  • 学习资料
  • TypeScript 介绍
    • TypeScript 是什么?
    • TypeScript 增加了什么?
    • TypeScript 开发环境搭建
  • 基本类型
  • 编译选项
    • 声明
    • 属性
    • 属性修饰符
    • getter 与 setter
    • 方法
      • static 静态方法
      • 实例方法
    • 构造函数
    • 继承 与 super
    • 抽象类
    • 接口
      • interface 定义接口
      • implements 使用接口
      • 多重继承
    • 泛型


学习资料

【尚硅谷TypeScript教程(李立超老师TS新课)】

TypeScript演练场

TypeScript 介绍

TypeScript 是什么?

TS学习与实践_第1张图片

TypeScript 增加了什么?

TS学习与实践_第2张图片

TypeScript 开发环境搭建

  1. 下载Node.js https://nodejs.com.cn/
  2. 安装Node.js
  3. 使用npm全局安装typescript
    • 进入命令行
    • 输入:npm i -g typescript
  4. 创建一个ts文件
  5. 使用tscts文件进行编译
    • 进入命令行
    • 进入ts文件所在目录
    • 执行命令:tsc 文件名.ts

基本类型

  • 类型声明

    • 类型的声明是TS非常重要的一个特点
    • 通过类型声明可以指定TS中的变量(参数、形参)的类型
    • 指定类型后,当为变量赋值时,TS编译器会自动检查是否符合类型声明,符合则赋值,否则报错
    • 简而言之,类型声明给变量设置了类型,使得变量只能存储某种类型的值
    • 语法:
      let 变量: 类型;
      
      let 变量: 类型 =;
      
      function fn(参数:类型, 参数:类型): 类型{
      	...
      }
      
  • 自定类型判断

    • TS拥有自动的类型判断机制
    • 当对变量的声明和赋值是同时进行的,TS编译器会自动判断变量的类型
    • 所以如果你的变量的声明和赋值是同时进行的,可以省略掉类型声明
  • 类型

    类型 例子 描述
    number 1, -33, 2.5 任意数字
    string ‘hi’, “hi” 任意字符串
    boolean true、false 布尔值true 或 false
    字面量 其本身 限制变量的值就是该字面量的值
    any * 任意类型
    unknown * 类型安全的any
    void 空(undefined) 没有值(或 undefined)
    never 没有值 不能是任何值
    object {name:‘孙悟空’} 任意的JS对象
    array [1,2,3] 任意JS数组
    tuple [4,5] 元素,TS新增类型,固定长度数组
    enum enum{A,B} 枚举,TS中新增类型
  • number

    let decimal: number = 6;
    let hex: number = 0xf00d;
    let binary: number = 0b1010;
    let octal: number = 0o744;
    let big: bigint = 100n;
    
  • boolean

    let isDone: boolean = false;
    
  • string

    let color: string = "blue";
    color = 'red';
    
    let fullName: string = `Bob Bobington`;
    let age: number = 37;
    let sentence: string = `Hello, my name is ${fullName}.
    
    I ll be ${age +1} years old next month.`
    
    
  • 字面量
    也可以使用字面量去指定变量的类型,通过字面量可以确定变量的取值范围

    let color: 'red' | 'blue' | 'black';
    let num: 1 | 2 | 3 | 4 | 5;
    
  • any

    let d: any = 4;
    d = 'hello';
    d == true;
    
  • unknown

    let notSure: unknown = 4;
    notSure = 'hello';
    
  • void

    let unsable: void = undefined;
    
  • never

    function error(message: string): never {
        throw new Error(message);
    }
    
  • object(没啥用)

    let obj: object = {};
    
  • array

    let list: number[] = [1,2,3];
    let list: Array<number> = [1,2,3];
    
  • tuple

    let x: [string, number];
    x = ["hello",10];
    
  • enum

    enum Color {
        Red,
        Green,
        Blue
    }
    let c: Color = Color.Green;
    
    enum Color {
        Red = 1,
        Green = 2,
        Blue = 4
    }
    let c: Color = Color.Green;
    
  • 类型断言

    • 有些情况下,变量的类型对于我们来说是很明确,但是TS编译器却不清楚,此时,可以通过类型断言来告诉编译器变量的类型,断言有两种形式:
      • 第一种
        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;
        

编译选项

  • 自动编译文件
    • 编译文件时,使用-w指令后,TS编译器会自动监视文件的变化,并在文件发生变化时对文件进行重新编译。
    • 示例:
      • tsc xxx.ts -w
  • 自动编译整个项目
    • 如果直接使用tsc指令,则可以自动将当前项目下的所有ts文件编译为js文件。
    • 但是能直接使用tsc指令的前提是,要先在项目目录下创建一个ts的配置文件tsconfig.json
    • tsconfig.json是一个JSON文件,添加配置文件后(添加配置文件命令,在VSCode终端中输入tsc -init),只需要tsc指令即可完成对整个项目的编译。
    • 配置选项:
      • include
        • 定义希望被编译文件所在的目录
        • 默认值:[**/*]
        • 示例:
          "include":["src/**/*","tests/**/*"]
          
          上述例子中,所有src目录和tests目录下的文件都会被编译
      • exclude
        • 定义需要排除在外的目录
        • 默认值:["node_modules","bower_components","jspm_packages"]
        • 示例:
          "exclude": ["./src/hello/**/*"]
          
          上述示例中,src和hello目录下的文件都不会被编译
      • extends【了解即可】
        • 定义被继承的配置文件
        • 示例:
          • "extends": "./configs/base"
            上述示例中,当前配置文件会自动包含config目录下base.json中所有配置信息
      • files【了解即可】
        • 指定被编译文件的列表,只需要编译的文件少时才会用到
        • 示例:
          "files": [
          	"core.ts",
          	"sys.ts",
          	"types.ts"
          ]
          
          列表中的文件都会被TS编译器所编译
      • compilerOptions(重点,以下为compilerOptions的子选项)
        • 编译器的选项
          		{
          		    "compilerOptions": {
          		        "target": "ES6",
          		        "module": "system",
          		        "outDir": "./dist",
          		        // "outFile": "./dist/app.js",
          		        "allowJs": false,
          		        "checkJs": false,
          		        "removeComments": false,
          		        "noEmit": false,
          		        "noEmitOnError": true,
          		        "strict": true,
          		        "alwaysStrict": true,
          		        "noImplicitAny": false,
          		        "noImplicitThis": true,
          		        "strictNullChecks": true
          		    } 
          		}
          
        • target
          • 用来指定ts被编译为的es版本
          • 可选项:ES3(默认)、ES5、ES6/ES2015、ES7/ES2016、ES2017、ES2018、ES2019、ES2020、ESNext
        • module
          指定要使用的模块化的规范
          'none', 'commonjs', 'amd', 'system', 'umd', 'es6', 'es2015', 'es2020', 'es2022', 'esnext', 'node16', 'nodenext'.
          
        • lib
          用来指定所需要的库,一般不用动,有默认值
          可选项:‘es5’, ‘es6’, ‘es2015’, ‘es7’, ‘es2016’, ‘es2017’, ‘es2018’, ‘es2019’, ‘es2020’, ‘es2021’, ‘esnext’, ‘dom’, ‘dom.iterable’, ‘webworker’, ‘webworker.importscripts’, ‘webworker.iterable’, ‘scripthost’, ‘es2015.core’, ‘es2015.collection’, ‘es2015.generator’, ‘es2015.iterable’, ‘es2015.promise’, ‘es2015.proxy’, ‘es2015.reflect’, ‘es2015.symbol’…
          
        • outDir
          • 用来指定编译后文件所在的目录
          "outDir": "./dist"
          
        • outFile
          将代码合并成一个文件,设置outFile后,所有的全局作用域合并在一个文件中,module中只有’amd’‘system’ 支持outFile
          "outFile": "./dist/app.js"
          
        • allowJs
          是否对js文件进行编译,默认是false,如果项目中某些模块用js写,可能需要编译
          "allowJs": false
          
        • checkJs
          检查js是否符合语法规范,默认是false
          "checkJs": false
          
        • removeComments
          是否移除注释,默认是false
          "removeComments": true
          
        • noEmit
          不生成编译后的文件,默认是false
           "noEmit": true
          
        • noEmitOnError
          当有错误时不生成编译后的文件,默认是false
          "noEmitOnError": false
          
        • strict
          所有严格模式的总开关,默认false(配置后相当于以下配置全都开启)
          "strict": true
          
        • alwaysStrict
          用来设置编译后的文件是否适用于严格模式,默认是false
          "alwaysStrict": true
          
        • noImplicitAny
          当某个变量不指定类型时,使用any类型
          "noImplicitAny": true
          
        • noImplicitThis
          不允许类型不明的 this
          "noImplicitThis": true
          
        • strictNullChecks
          严格地检查空值,默认false
          "strictNullChecks": true
          

声明

用关键字class来声明一个类

class Person{
	...
}

属性

在TS中类的属性一共有三种,在属性面前添加相应的修饰符便可

class Person{
	name:string = "zhubajie" // 实例属性
	static age = 89 // 类属性
	readonly addr:string = "高老庄" // 只读属性
}
  • 实例属性
    直接定义的属性属于实例属性
    他必须通过类实例化之后才能使用
  • 类属性
    static开头的属性为类属性
    他可以通过类直接访问Person.age
  • 只读属性
    readonly定义的属性为只读属性,不可修改
    readonly也可以放再static后面

属性修饰符

pubilc 公共属性,可以再任意位置访问和修改(实例属性,实例化之后访问)
private 私有属性,只能在类的内部进行访问和修改(一般声明的时候我们会以_开头)
protected 受保护的属性,只能在当前类和当前类的子类中进行访问

class Person{
    public name = "SunWuKong"
    private age = 30
    protected sex = "male"
}

const person = new Person()
console.log(person.name)
console.log(person.age) // 错误 只能在Person这个类中进行访问
console.log(person.sex)  // 错误 只能在Person这个类和其子类中访问

此外,还有readOnly属性,以他修饰的属性只能读取不能修改

getter 与 setter

  • 类中的每一个属性内置getter方法和setter方法
    getter 方法用于获取属性
    setter 方法用于设置属性
  • 这样,我们可以对属性读取和操作做一些拦截,设置如下
    class Person1{
        private _name:string
        constructor(name:string){
            this._name = name;
        }
    
        set name(value:string){
            this._name = value
        }
    
        get name(){
            return this._name
        }
    }
    
    当我们进行读取的时候,其实是走的get这个逻辑
    当我们对于属性进行赋值的时候,其实是走的set这个逻辑

方法

static 静态方法

经过static关键字修饰的方法属于类方法,可以通过类直接使用

class BaJie{
    name = "BaJie"
    static age = 18
    static sayName(){
        console.log("八戒")
    }
}

// 通过类直接访问
BaJie.sayName()
console.log(BaJie.age);

const bajie = new BaJie()
bajie.sayName() // 实例化之后不可访问

当有不规范的语法的时候,ts就不会进行编译,如上面的编译如下

var BaJie = /** @class */ (function () {
    function BaJie() {
        this.name = "BaJie";
    }
    BaJie.sayName = function () {
        console.log("八戒");
    };
    BaJie.age = 18;
    return BaJie;
}());
// 通过类直接访问
BaJie.sayName();
console.log(BaJie.age);

实例方法

在类中直接定义的方法为实例方法,没有任何关键字的修饰

这种方法只能在类实例化之后进行使用

class BaJie{
    name = "BaJie"
    age = 18
    sayName(){
        console.log("八戒")
    }
}

// 通过类直接访问
BaJie.sayName() // 错误的访问方法
console.log(BaJie.age); // 错误的访问方法
// 同样,实例化之后也是可以访问的
const bajie = new BaJie()
bajie.sayName() 
console.log(bajie.name);

构造函数

class Person{
	name:string;
	age:nubmer;
    constructor(name:string,age:number){
        this.name = name
        this.age = age
    }
}

const p1 = new Person('张三',18);
const p2 = new Person('李四',20);

console.log(p1);
console.log(p2);

constructor被称为构造函数
构造函数会在对象创建时调用

继承 与 super

// 父类
class Animal{
    name:string;
    age: number;
    constructor(name:string,age:number){
        this.name = name;
        this.age = age
    }
    sayName(){
        console.log(this.name)
    }
}
// 子类
class Dog extends Animal{
    run(){
        console.log(`${this.name}run`);
    }
}
class Cat extends Animal{
    sayName(){
        console.log(`我是${this.name}`);
    }
}
const dog = new Dog("旺财",19)
const cat = new Cat("汤姆",20)
dog.sayName()
dog.run()
cat.sayName()

可以将代码复制到 TypeScript演练场 运行

TS学习与实践_第3张图片
我们使用extends关键字来进行继承,其中被继承的Animal为父类,Dog为子类
继承之后,子类会拥有父类的一切属性和方法
子类也可以自己定义一些方法,如上面例子中的run
子类也可以写与父类相同的方法,这样执行方法的时候会执行子类的方法,叫做方法重写Cat类中重写了sayName方法)

抽象类

abstract class Animal{
    name:string;
    constructor(name:string){
        this.name = name;
    }

    abstract sayName():void;
}

class Dog extends Animal{
    age:number;
    constructor(name:string,age:number){
        super(name);
        this.age = age;
    }
    sayName(): void {
        console.log(`我是${this.name},我今年${this.age}岁了`);
    }
}

const dog = new Dog("旺财",23)
dog.sayName() // 我是旺财,我今年23岁了

abstract关键字来定义抽象类和抽象方法

  • 抽象类
    抽象类不能用来创建对象
    抽象类只能用于继承(说明类中有哪些属性,哪些方法)
    在抽象类中可以添加抽象方法(如sayName方法)
  • 抽象方法
    抽象方法没有方法体(如sayName方法),且只能定义在抽象类中
    子类必须对于抽象类中的抽象方法进行复写

接口

接口用于描述一个类或者一个对象的结构,描述他们的属性和方法,所以接口可以当做一个类的声明

interface 定义接口

我们使用interface来定义一个接口,定义的方法全部为抽象方法,必须重写

接口用来定义一个类结构,用来定义一个类中应该包含哪些属性和方法

同时接口也可以当成类型声明去使用

interface myInterface{
    name:string,
    age:number,
    sex:"male"|"female",
    sayName():void
}

implements 使用接口

一般我们使用implements关键字来使用接口

class Person implements myInterface{
    name: string;
    age: number;
    sex: "male" | "female";
    sayName(): void {
        console.log(this.name);
    }
}

多重继承

使用extends来进行接口的继承,且后可以跟多个接口,实现多重继承

interface Obj {
    [propName:string]:any
}

interface myInterface{
    name:string,
    age:number
}

interface IPerson extends myInterface,Obj{
    sex:"male"|"female",
    sayName():void
}

class Person implements IPerson{
    name: string;
    age: number;
    sex: "male" | "female";
    hobby:"read"|"write"
    sayName(): void {
        console.log(this.name);
        
    }
}

泛型

在指定函数或者类的时候,如果遇到类型不明确的话,就可以使用泛型(不先指定类型,使用的时候进行类型的转换)

一般在声明的变量后面加一个尖括号来声明泛型
TS学习与实践_第4张图片
当我们进行类型转换后,编辑器就会有相应的提示

当然我们也可以不指定泛型,ts会进行自动的类型转换

  • 指定多个泛型
    function fn1<T,K>(a:T,b:K):K{
        console.log(a);
        return b
    }
    
    fn1<number,string>(1,'hello')
    
  • 定义类
    class Person3<T>{
        name:T
        constructor(name:T){
            this.name = name
        }
    }
    
    const person4 =  new Person3<string>("Jack")
    console.log(person.name);
    
  • 泛型与接口
    泛型也可以继承接口,使用extends关键字,他表示泛型必须满足接口的条件
    interface IPerson1{
        name:string,
        age:number
    }
    
    function fn2<T extends NameInterface>(a:T):string{
        return a.name
    }
    
    fn2<IPerson1>({name:"小敏",age:10})
    

你可能感兴趣的:(前端,学习与实践,typescript)