首页 前端知识 Type Script 学习笔记

Type Script 学习笔记

2024-05-25 09:05:19 前端知识 前端哥 628 91 我要收藏

一、什么是TypeScript

  1. 以javaScript 为基础构建的语言,可以在任何支持javaScript的平台中运行,Ts不能被js解析器直接执行,需要将ts文件编译成js文件
  2. 一个javaScript的超集,TypeScript扩展了JavaScript并添加了类型

二、TypeScript增加了什么

(1)类型
(2)支持ES的新特性
(3)添加Es不具备的新特性
(4)丰富的配置选项
(5)强大的开发工具

三.TypeScript开发环境搭建

> (1)下载node.js,安装node.js 
> (2)使用npm全局安装TypeScript 
> 	 ①进入命令行
> 	 ②输入:npm i -g typescript 
> (3)创建一个ts文件
> (4)适用ts对ts文件进行编译 
	> ①进入命令行 
	> ②进入ts文件所在目录 
	> ③执行命令tsc xxx.ts

四、基本类型

类型声明:

1)类型声明是TS非常重要的一个特点
2)通过类型声明可以指定TS中变量(参数、形参)的类型
3)指定类型后,当为变量赋值时,TS编译器会自动检查是否符合类型声明,符合则赋值,否则报错
4)简而言之,类型声明给变量设置了类型,使得变量只能存储某种类型的值

语法:

let 变量:类型;
let 变量:类型 = 值;
function fn(参数:类型,参数:类型):类型 {
}

自动类型判断:

a.Ts拥有自动的类型判断机制
b.当对变量的声明和赋值是同时进行的,ts编译器会自动判断变量的类型
c.所以如果你的变量的声明和赋值是通过是进行的,可以省略掉类型声明。

类型:

类型例子描述
number1,-33,2.5任意数字
String‘hi’,”h1”,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中新增类型

类型使用样例:


//let a:string
// 也可以直接使用字面量进行类型声明
let a:10 // 字面量相当于常量,他不能被修改

// 可以使用|连接多个类型(联合类型)
let b:'male' | 'female'; //声明b可以是male 或者female
let c:boolean|string;

/Any///


// any 表示的是任意类型,一个变量设置类型为any后相当于对该变量关闭了ts的类型检测
// 使用TS时,不建议使用any类型
// let d:any; 显式any
// 声明变量如果不指定类型,则TS解析器会自动判断类型变量的类型为any(隐式any)
let d;
d = 10;
d = 'hello'
d = false
d = {}
let s:string;
// d的类型式any,它可以赋值给任意变量
s = d;



// unknown 表示未知类型的值
let e:unknown;
e = 10;
e = 'hello';
e = true
let t:string;
// e的类型是unknown未知的类型,将它赋值给已知类型string时会报错:Type 'unknown' is not assignable to type 'string'.ts(2322)
// t = e;
//unknown 实际上是一个类型安全的any,unknown类型的变量不能直接赋值给其他变量
// 解决办法1:
if(typeof e === 'string') {
    t = e
}
// 解决办法2:类型断言:可以用来告诉解析器变量的实际类型(意思是我们知道e是字符串,编译器不知道,
// 我们告诉编译器它就是字符串,让它放心的用吧)
/**
 * 类型断言:
 * 语法:
 *  变量 as 类型
 * <类型>变量
 */
s = e as string;
//或写成
s = <string>e;




// void 用来表示返回值为空,以函数为例,就表示没有返回值函数
function fn():void{
   //   return '123' // 当返回值为void时,会报错Type 'string' is not assignable to type 'void'.ts(2322),可以写成return;或者return undefined;或者return null;
 }



// never 表示永远不会返回结果
function fn2():never{
    throw new Error('报错了');
    //   return '123' // 当返回值为void时,会报错Type 'string' is not assignable to type 'void'.ts(2322),可以写成return;或者return undefined;或者return null;
 
 }



// object表示一个js对象,不常用,因为万物皆对象,
 let f:object;
 f = {};
 f = function(){}
 //object 常用方式如下:
 // {} 用来指定对象中可以包含哪些属性
// 语法:{属性名:属性类型}
 // 在属性名后面加上?,表示属性是可选的
 let g:{name:string, age?:number} //?表示这个属性后面赋值有也行,没有也行
 g={name:'孙悟空'};
 // [propName: string]: any 表示任意类型的属性
 let h: {name: string,[propName: string]: any}
 h = {name: '猪八戒', age: 18}



/*
 *设置函数结构的类型声明
  语法:(形参:类型,形参:类型...)=>返回值
 */
 let i:(a:number,b:number)=>number;
//  i = function (n1, n2):number{
//     return n1 + n2;
//  }



/**
 * 数组的类型声明:
 *  类型[];
 *  Array<类型>
 */
// string[]表示字符串数组
let j:string[];
let k:Array<number>;
let l:Array<any>;



/**
 * 元组:元组就是固定长度的数组
 * [类型,类型,类型]
 */
let m:[string,string]
m = ['孙悟空','猪八戒']



/**
 * 枚举
 */
enum Gender{
    Male = 0,
    female = 1
}
let n:{name:string,gender:Gender}
n={
    name: '孙悟空',
    gender: Gender.Male
}
console.log(n.gender === Gender.Male)


//类型的别名
type mytype = 1|2|3|4|5;
let r:mytype
r=5;
//r=6; // Type '6' is not assignable to type 'mytype'.ts(2322)


五、Ts编译配置

项目新建tsconfig.json

{
    /*tsconfig.json 是ts编译器的配置文件,ts编译器可以根据她的信息来对代码进行编译
    "include": ["],用来指定哪些ts文件需要被编译,一个/*表示任意文件,两个/**表示任意文件目录
    "exclude": 不需要被编译的目录,默认值["node_modules","bower_components","jspm_packages"]
    "extends":"", 继承,如果我有两个tsconfig文件,我又不想在写一份,可以用该属性
    "files":[xxx.ts,xxx.ts]指定被编译的文件列表

    compilerOptions{} 编译器配置
        target: 用来指定ts 编译后的Es版本,默认ES3,,可选值es3,es5,es6,es2015,es2016,es2017,es2018,es2019,es2020,esnext
        lib[] 用来指定项目中要使用的库,一般不动他
        module: 指定要使用的模块化规范,可选值:none commonjs amd system umd es6 es2015 es2020 exnest
        outDir: 用来指定版以后文件所在的目录
        outFile: 将代码合并成一个文件,设置outFile 后 所有的全局作用域中的代码会合并到同一个文件中。
        allowJs: 是否对js文件进行编译,默认false
        checkJs: 是否检查js文件语法
        removeComments: 编译时是否去除注释
        noEmit: 不生成编译后的文件
        noEmitOnError: 当有错误时不生成编译文件

        // 语法检查的属性
        alwaysStrict: 严格模式,用来设置编译后的文件是否使用严格模式,默认false
        noImplicitAny: 不允许使用隐式any
        noImplicitThis: 不允许使用不明确类型this
        strictNullChecks: 严格的检查空值,
        strict: 所有严格模式的总开关,这个属性一定要写在最上面
    */
    "compilerOptions": {
        "module": "commonjs",
        "target": "ES5",
        "sourceMap": true,
        "outDir": "./dist",
       // "outFile": "./dist/app.js"
       "allowJs": false,
       "checkJs": false,
       "removeComments": false,
       "noEmit": false,
       "noEmitOnError": false,
       "strict": false,
       "alwaysStrict": false,
       "noImplicitAny": false,
       "noImplicitThis": false,
       "strictNullChecks": false
    },
    "exclude": [
        "node_modules"
    ],

    "include": ["./src/**/*"]
}

六、Webpack

1.命令行输入:npm init -y 对项目进行初始化。会自动生产package.json文件
在这里插入图片描述
2.安装wabpack所需要的依赖 npm i -D webpack webpack-cli typescript ts-loader
其中-D为开发环境,webpack-cli为webpack命令行工具,typescript 包,ts-loder为ts和webpack整合工具
根目录新建wabpack.config.js文件

/ 引入一个包
const path = require('path')

// webpack 中的所有的信息都应该写在module.exports中
module.exports = {
    // 指定入口文件
    entry:'./src/index.ts',
    // 指定打包文件所在目录
    output:{
        // 指定打包文件的目录
        path: path.resolve(__dirname,'dist'),
        //打包后文件的名字
        filename:"bundle.js"

    },

    //指定webpack打包时要使用的模块
    module:{
        // 指定要加载的规则
        rules:[
            {
                // test 指定的时规则生效的文件
                test: /\.ts$/,
                // 要使用的loader
                use: 'ts-loader',
                // 要排除的文件
                exclude: /node_modules/
            }
        ]
    }
}

3.新建tsconfig.json文件

{
    "compilerOptions": {
        "module": "ES2015",
        "target": "ES2015",
        "strict": true
    }
}

4.在package.json文件中的scripts加入build:webpack属性用于打包

"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack"
  },

5.后续使用npm run bulid进行打包编译

命令行执行npm i -D html-webpack-plugin,帮助我们自动生成html文件
1.webpack.config.js 引入webpack-plugin

// 引入html插件
const HTMLWebpackPlugin = require('html-webpack-plugin')
    //在module.exports中添加如下代码,template为自定义html,如过没有该属性,它会在编译时自动创建一个html
    plugins:[
        new HTMLWebpackPlugin({
            // title: "这是自定义的title"
            template:"./src/index.html"
        })
    ]
}

2.Webpack开发服务器: npm i -D webpack-dev-server
安装完之后,在package.json的scripts属性下添加start:”webpack serve --open chrome.exe”

"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack",
    "start": "webpack serve --open chrome.exe"
  },

使用npm run start进行编译,编译完成后自动打开谷歌浏览器
3.npm i -D clean-webpack-plugin ,每次在编译时都会先清空dist文件夹,保证每次都是最新的文件
安装完后,在webpack.config.js文件下引入:
/ 引入clean插件

const {CleanWebpackPlugin } = require('clean-webpack-plugin')
// 并在plugins下添加
 plugins:[
        new CleanWebpackPlugin(),...
    ]

4.引用模块编译报错,如使用import引入某个js 或ts,编译时会出错,需要在webpack.config.js加入如下配置

/ 用来设置引用模块
    resolve:{
        extensions:['.ts','.js']
    }

Bable 解决兼容性问题,tsconfig可以设置es版本,它只是语法上的转换,bable可以兼容不同的浏览器,
npm i -D@babel/core @babel/preset-env babel-loader core-js
安装完成后,打开webpack-config.js
在module.rules下use改为

//指定webpack打包时要使用的模块
    module:{
        // 指定要加载的规则
        rules:[
            {
                // test 指定的时规则生效的文件
                test: /\.ts$/,
                // 要使用的loader
                use: [{
                    // 指定加载器
                    "loader":"babel-loader",
                    // 设置bable
                    Option:{
                        // 设置预定义的环境
                        presets:[
                            [   // 指定环境的插件
                                "@babel/preset-env",
                                // 配置信息
                                {
                                    // 要兼容的目标浏览器
                                    targets: {
                                        "chrome": "88",
                                        "ie":"11"
                                    },
                                    // 指定corejs的版本
                                    "corejs":"3",
                                    // 使用corejs的方式,‘usage’表示按需加载
                                    "useBuiltIns":'usage'
                                }]
                        ]
                    }
                },'ts-loader'], //它是由后向前执行,先将ts转换为js,在将js转换为浏览器兼容的js版本
                // 要排除的文件
                exclude: /node_modules/
            }
        ]
    },

Webpack 打包时不在最外层添加箭头函数,ie不支持箭头函数。
在这里插入图片描述

在webpack-config.js,在output下添加environment属性

output:{
        // 指定打包文件的目录
        path: path.resolve(__dirname,'dist'),
        //打包后文件的名字
        filename:"bundle.js",
        // 告诉webpack 打包时不使用箭头函数
        environment:{
            arrowFunction: false
        }

    },

七、面向对象

面向对象是程序中一个非常重要的思想,它被很多同学理解成了一个比较难,比较深奥的问题,其实不然,面向对象很简单,简而言之,就是程序之中所有操作都需要通过对象来完成。
举例说明:
1.操作浏览器要使用window对象
2.操作网页要使用docurment对象
3.操作控制台要使用console对象
一切操作都需要对象,也就是所谓的面向对象,那么对象到底是什么呢? 这就要先说到程序是什么,计算机程序的本质就是对显示十五的抽象,抽象的反义词就是具体,比如,照片是对一个具体人的抽象,汽车模型是对具体汽车的抽象,程序也是对事物的抽象,在程序中我们可以表示一个人,一条狗,一把枪,一颗子弹等等所有事物,一个事物到了程序中就变成了一个对象。
在程序中,所有的对象都被分成了两个部分数据和功能,以人为例,人的姓名,性别,年龄,身高,体重等属于数据,人可以说话,走路,吃饭睡觉这些属于人的功能,数据在对象中被成为属性,而功能就被称为方法,所以简而言之,在程序中一切皆是对象。

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

/ 使用class关键字来定义一个类
/**
 * 对象中主要包含了两个部分
 *  属性
 *  方法
 */
class Person{
    /*
      直接定义的属性是实例属性,需要通过对象实例去访问:
      const per = new Person();
        console.log(per.name)
      使用static开头的属性是静态属性(类属性)
      console.log(Person.age)

      readonly 开头的属性,表示只读的属性,不能修改
    */
    // 定义实例属性
    name: string = '孙悟空';
    
    // 在属性前使用static 关键字可以定义类属性(静态属性)
    static age: number = 18;

    // 定义方法
    /**
     * 如果方法以static开头,则方法就是类方法,可以直接通过类调用
     */
    sayHello(){
        console.log('hello 大家好!')
    }
}
const per = new Person();
console.log(per.name)
console.log(Person.age)
per.sayHello()

2.构造函数和this

class Dog {
    name:string;
    age:number;

    // constructor被称为构造函数
    // 构造函数会在对象创建时调用
    constructor(name:string,age:number){
        console.log('构造函数执行了~~~')
        //在实例方法中this就表示当前的实例,
        // 在构造函数中当前对象就是当前新建的那个对象
        console.log(this)
        this.name=name
        this.age=age
    }

    bark() {
        // alert('汪汪汪')
        // 在方法中可以通过this来表示当前调用方法的对象
        console.log(this.name)
    }
}

const dog1 = new Dog('小黑',19)
const dog2 = new Dog('小白',2)
console.log(dog1)
dog1.bark() // 小黑
dog2.bark() // 小白

3.继承和重写

class Animal {
    name: string;
    age: number;
    constructor(name:string,age:number){
        this.name=name;
        this.age=age;
    }
    sayHello(){
        console.log("嘎嘎嘎")
    }
}

// 表示猫的类
class Cat extends Animal{
    // 
    sayHello(){
        console.log('喵喵喵')
    }
}

/**
 *  Dogs extends Animal
 *  -此时,Animal被称为父类,Dog被称为子类
 *  - 使用继承后,子类将会拥有父类所有的方法和属性
 *  - 通过继承可以将多个类中共有的代码写在一个父类中,这样只需要写一次即可让所有子类都同时拥有父类的属性,
 *   -如果希望在子类中添加父类没有的属性或方法,直接加就行
 *   - 如果在子类中添加了和父类相同的方法,则子类方法会覆盖父类的方法
 *         这种子类覆盖父类方法的形式,我们称为重写
 */
// 表示狗的类
class Dogs extends Animal{
   run(){
    console.log(this.name + "哈利波特骑着扫帚飞~")
   }
   sayHello(){
     console.log('汪汪汪')
   }
}

const cat = new Cat("小黑猫",4)
const dogs = new Dogs("小黑猫",4)

4.Supper

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

        sayHello(){
            console.log('hahaha')
        }
    }
    class Dog extends Animal {
        age: number
        constructor(name:string,age:number){
            // 如果在子类中写了构造函数,在子类构造函数中必须调用父类构造函数supper()
            super(name) // 调用父类的构造函数
            this.age = age
        }
        sayHello() {
            // 在类方法中,super就表示当前类的父类
            super.sayHello()
        }
    }

5.抽象

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

    class Cat extends Animal {
        sayHello() {
            console.log('喵喵喵')
        }
    }

6.接口

// 描述一个对象的类型

   type myType = {
    name: string,
    age: number
   }

   const obj:myType ={
    name: 'aaa',
    age: 12
   }

   /**
    * 接口用来定义一个类的结构,用来定义一个类中应该包含哪些属性和方法
    * 同时接口可以当成类型声明去声明,
    */
   interface myInterface {
     name: string,
     age: number
   }

   interface myInterface {
    gender: string
  }

   const obj1:myInterface ={
    name: 'aaa',
    age: 12,
    gender: '男'
   }

   /**
    * 接口可以在定义类的时候去限制类的结构
    * 接口中的所有的属性都不能有实际的值
    * 接口只定义对象的接口,而不考虑实际值
    *   在接口中所有的方法都是抽象方法
    */
   interface myInter {
    name: string;
    sayHello():void;
   }

   /**
    * 定义一个类时,可以使用类去实现一个接口
    * 实现接口,就是使类满足接口的要求
    */
   class MyClass implements myInter{
       name: string;
       constructor(name:string) {
        this.name = name
       }
       sayHello(): void {
           console.log('大家好')
       }

   }

7.属性的封装

   // 定义一个表示人的 类
    class Person {
        // TS可以在属性前添加属性的修饰符
        /**
         * public 修饰的属性可以在任意位置访问(修改)默认值
         * private 私有属性,私有属性只能在类内部进行访问(修改)
         *      - 可以通过类中添加方法,使得私有属性可以被外部访问
         * protected 受保护的属性,只能在当前类和当前类的子类中访问(修改)
         */
        private _name:string;
        private _age:number;
        constructor(name:string,age:number){
            this._name=name;
            this._age=age;
        }
        
        /**
         * 
         * getter 用来读取属性
         * setter 用来设置属性
         *  -它们被称为属性的存取器
         */

        // 定义方法,用来获取name属性
        // getName() {
        //     return this._name
        // }
         
        // // 定义方法,用来设置name属性
        // setName(name:string) {
        //     return this._name = name
        // }

        // // 定义方法,用来获取name属性
        // getAge() {
        //     return this._age
        // }
         
        // // 定义方法,用来设置name属性
        // setAge(age:number) {
        //     if(age >= 0) {
        //         return this._age = age
        //     }
           
        // }

        // TS中设置getter方法的方式
        // 用起来和属性一样 console.log(per.name)
        get name(){
            return this._name
        }
        // 用起来和属性一样 per.name = '猪八戒'
        set name(name:string) {
            this._name = name
        } 
    }
    const per = new Person('孙悟空', 8)

    /**
     * 限制属性是在对象中设置的,属性可以任意的被修改
     * 属性可以任意被修改将会导致对象中的数据非常不安全
     */
    // per._age = 38

    // per.getName()
    // per.setName('猪八戒')

    console.log(per.name)
    per.name = '猪八戒'

语法糖

class A{
        num:number;
        constructor(num:number){
            this.num =num
        }
    }

可写成


class A{
        constructor(public num:number){
        }
    }

8.泛型

// function fn(a:number):number{
//     return a
// }

/**
 * 在定义函数或是类时,如果遇到类型不明确就可以使用泛型
 * T可以写其他字母都可以,它代表不明确类型,只有代码执行的时候,传进来什么类型就是什么类型
 */

function fn<T>(a: T):T{
 return a
}

// 可以直接调用具有泛型的函数
fn(10) // 不指定泛型,TS可以自动对类型进行推断
fn('10')
fn(false)

fn<string>('hello') // 指定泛型,

// 泛型可以直接指定多个
function fn2<T,K>(a:T,b:K):K{
    return b
}
fn2<number,string>(123,'344');

interface Inter {
    length: number;
}

// T extends Inter 表示泛型T必须是Inter实现类(子类)
function fn3<T extends Inter>(a:T):number{
return a.length
}

fn3({length: 10})

class MyClass<T> {
    name: T;
    constructor(name:T){
        this.name = name
    }
}
const mc = new MyClass<string>('孙悟空')
const mc1 = new MyClass(123)

9.安装css 解析器 npm i -D less less-loader css-loader style-loader
在wabpace.config.js中 module下加入

{
                test: /\.less$/,
                use: [
                    "style-loader",
                    "css-loader",
                    "less-loader"
                ]
            }

css兼容性处理:
npm i -D postcss postcss-loader postcss-preset-env

{
                test: /\.less$/,
                use: [
                    "style-loader",
                    "css-loader",
                    // 引入postcss
                    {
                      loader: "postcss-loader",
                      options: {
                        postcssOptions:{
                            plugins: [
                                ["postcss-perset-env",
                                {
                                    browsers: 'last 2 versions' // 兼容两个最新版本的浏览器
                                }]
                            ]
                        }
                      }
                    }"less-loader"
                ]
            }
转载请注明出处或者链接地址:https://www.qianduange.cn//article/9452.html
标签
评论
会员中心 联系我 留言建议 回顶部
复制成功!