Bootstrap

TypeScript学习总结

类型声明

//number类型
let a : number;
a=10

//string类型
let b : string;
b='hello'

//boolean 声明变量直接赋值
//let c : boolean = true
//如果变量声明与赋值是同时进行,ts可以自动对变量进行类型检测
let c = true;

//function
function sum(a:number,b:number):number{
    return a+b
}
sum(11,456)

//可以直接使用字面量进行类型声明 可以使用 | 连接多个类型
let a : 'red' | 'blue';//a只能被赋值为后面两个值
let c : boolean | string
c=true
c='hello'

//any 表示的是任意类型,一个变量设置any后相当于对该类型关闭了TS类型检测
let d :any;
d=true
d=111

//声明变量如果不指定类型,则TS解析器会自动判断变量类型为any (隐式any)
let d;
d=10
d='hello'

//unknown 表示未知类型的值
let e :unknown;
e=10
e='hello'

// d的值为any可以赋值给任意变量(并且会把自己赋值的变量的类型检测也给关了),但是unkonwn不行
let s:string;
//unknown实际上就是一个类型安全的any 不能直接赋值给其他变量
if(typeof e === "string"){
    s=e;//不报错
}
//直接 s=e 报错

//类型断言
/*
*语法:
*变量 as 类型
*<类型>变量
*/
//也可以使用类型断言 类型断言,可以用来告诉解析器变量的实际类型
s=e as string; //类型断言 形式一
s=<string>e; //类型断言 形式二

//void 用来表示空,以函数为例,就表示没有返回值
function fn():viod{
    
}

//never 表示永远不会返回结果  一般函数没有返回值就返回undefined,但是有一种函数就是用来抛出错误,就没有任何返回值了
function fn2():never{
    throw new Error('报错了!')
}

//object表示一个js对象 并没有什么作用,因为js中万物皆对象
let a: object;
a={};
a=function(){}
//所以声明对象可以用 {} 用来指定对象可以包含哪些属性
//语法 {属性名:属性值(类型)}
//属性名后面 ?: 表示该属性是可选的,可有可不有
//[propName:string]:any 表示可以有任意属性
let b:{name:string,age?:number};// ?: 表示该属性是可选的,可有可不有
b={name:'张三'}
let c: {name:string,[propName:string]:any}
c={name:'李四',age:18}

/*
*  设置函数结构的类型声明:
*     语法:(形参:类型,形参:类型 ...)=>返回值
*/
//字面量函数写法
let d: (a:number,b:number)=>number;

/*
*数组
* 类型[]
* Array<类型>
*/
//string[] 表示字符串数组
let e:string[];
//number[] 表示数值数组
let f: number[];
let g: Array<number> 与上述同义

/*
*元组,元组就是固定长度的数组
* 语法: 
* [类型,类型,类型]
*/
let h:[string,string]
h=['aa','bb']

/*
*enum 枚举
* 语法: 
*
*/
enum Gender{
    Male = 0,
    Female = 1
}
let i: {name:string,genter:Genter}
i={
    name:'sun',
    gender:Gender.Male
}

//&表示同时
let j: {name:string} & {age:number}
//j={name:'sun',age:18}

//类型别名
type myType = 1|2|3|4|5;
let k: myType;
k=5

类型

例子

描述

number

1, -33, 2.599

任意数字

string

'hi', "hello"

任意字符串

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中新增类型

编译选项

自动监控编译

tsc xxx.ts -w

在一个文件夹下,创建 tsconfig.json 文件,在用命令 tsc 就可以自动编译当前文件夹下的ts文件

{
    /*
    tsconfig.json 是ts编译器的配置文件,ts编译器可以根据它的信息来对代码进行编译
    "include" 用来指定哪些ts文件需要被编译
    "exclude" 不需要被编译的文件目录
        默认值:["node_modulex","bower_components","jspm_packages"]
    "extends" 定义被继承的配置文件
        "extends":"./config/base" 表示当前配置文件中会自动包含config目录下base.json中的所有配置信息
    "files" 指定被编译文件的列表,只有需要编译的文件少时才会用到
        "files":[
            "core.ts",
            "sys.ts",
            "types.ts"        
        ]
    
    */
    "include":[
        "./src/**/*"    // *任意文件   **任意目录
    ],
    "exclude":[
        "./sr/hello/**/*"    
    ],
    /*
    compilerOptions 编译器的选项
    它决定了我们编译器如何去对我们这个ts文件进行编译
    
    */
    "compilerOptions":{
        //target 用来指定被编译的js版本
        "target":"es2015", //esnest表示最新的es版本
        //module 用来指定使用的模块规范
        "module":"es2015", //CommonJS、UMD、AMD、System、ES2020、ESNext、None
        //lib 用来指定项目中要使用的库
        "lib":["dom"],
        //outDir 用来指定编译后文件所在目录
        "outDir":"./dist",
        //outFile 将代码合并成一个文件,所有全局作用域中的代码会合并到同一个文件中
        "outFile":"./dist/app.js",
        //是否对js文件进行编译,默认是false
        "allowJs":false,
        //checkJs 是否检查js代码语法规范,默认是false
        "checkJs":false,
        //removeComments 是否移除注释,默认值false
        "removeComments":true,
        //noEmit 不对代码进行编译
        "noEmit":false,
        //当有错误的时候不生成编译文件
        "noEmitOnError":false,
        //sourceMap 是否生成sourceMap
        "sourceMap":false,
        
        //严格检查的总开关
        "strict":false //如果是false表示以下所有的严格检查都关闭,true表示都开启
        //用来设置编译后的文件是否使用严格模式,默认false
        "alwayStrict":false,
        //不允许隐式any类型
        "noImplicitAny":true,
        //不允许不明确类型的this
        "noImplicitThis":false,
        //严格检查空值
        "strictNullChecks":true  
    }
}

webpack

使用webpack配置ts编写环境,需要先下载如下几个包

npm i -D webpack webpack-cli webpack-dev-server typescript ts-loader clean-webpack-plugin html-webpack-plugin

webpack.config.js

//引入一个有关路径的包
const path = require('path');
// 引入html插件
const HTMLWebpackPlugin = require("html-webpack-plugin")
// 引入每次打包之前先清除打包文件的插件
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
// webpack所有配置信息
module.exports={
    optimization:{
        minimize: false // 关闭代码压缩,可选
    },
    // 定义入口文件
    entry:"./src/index.ts",
    //此选项控制是否生成,以及如何生成 source map。
    devtool: "inline-source-map",
    devServer: {
        contentBase: './dist'
    },
    // 指定打包文件所在目录
    output:{
        // 指定打包文件目录
        path:path.resolve(__dirname,'dist'),
        // 打包后文件的文件
        filename:"bundle.js",
        // 告诉webpack不使用箭头函数
        environment:{
            arrowFunction:false
        }
    },
    // 用来设置引用模块
    resolve: {
        extensions: [".ts", ".js"]
    },
    // 指定webpack打包要使用模块
    module:{
        // 指定要加载规则
        rules:[
            {
                //test 指定的是规则生效文件
                test:/\.ts$/,
                // 使用什么loader进行
                use:[
                    //配置babel
                    {
                        // 指定加载器
                        loader:"babel-loader",
                        // 设置babel
                        options:{
                            // 设置预定义环境
                            presets:[
                                [
                                    // 指定环境插件
                                    "@babel/preset-env",
                                    // 配置信息
                                    {
                                        // 要兼容的目标浏览器
                                        targets:{
                                            "chrome":"88",
                                            "ie":"11"
                                        },
                                        // 指定corejs版本
                                        "corejs":"3",
                                        // 使用corejs的方式"usage" 表示按需加载
                                        "useBuiltIns":"usage"
                                    }
                                ]
                            ]
                        }
                    },
                    'ts-loader'
                ],
                // 要排除的文件
                exclude:/node-module/
            }
        ]
    },
    // 配置webpack插件
    plugins:[
        new CleanWebpackPlugin(),
        new HTMLWebpackPlugin({
            // title:"这是一个自定义插件"
            template:'./src/index.html'
        }),
    ]
}

面向对象

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

使用static开头的属性是静态属性(类属性),可以直接通过类去访问
Person.name

readonly开头的属性表示一个只读的属性无法修改

*/
class Person{
    //定义实例属性
    name:string = '孙悟空';
    
    //在属性前使用static关键字可以定义类属性(静态属性)
    static age:number = 18;
    
    //定义方法
    sayHello(){
        console.log('hello,大家好')    
    }
}

const per = new Person();
console.log(per.name)

构造函数

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

继承 super

class Animal{
    name:string;
    age:number;
    constructor(name:string,age:number){
        this.name=name
        this.age=age
    }
    bark(){
        console.log('动物在叫');
    }
    sayHello(){
        console.log('说你好');
    }
}

// dog继承animal
/*
-此时dog被称为子类 animal被称为父类
-使用继承后,子类将会拥有父类所有的方法和属性
-通过继承可以将多个类中共有的代码写在一个父类中
    这样只需要写一次即可让所有子类都同时拥有父类中的属性和方法
    如果希望在子类中添加一些父类中没有的属性或方法直接加就行
-如果在子类中添加了和父类相同的方法,则子类的方法会覆盖父类的方法
    这种子类覆盖父类的方法,我们称为方法重写

*/
class Dog extends Animal{
    sound:string

    constructor(name:string,age:number,sound:string){
        // 如果子类写了构造函数,在子类构造函数中必须对父函数进行调用
        super(name,age) //调用父类构造函数
        this.sound=sound
    }

    run(){
        console.log('狗子在跑');
    }
    // 重写
    bark(){
        console.log('汪汪汪');
    }
    sayHello(){
        // 在类的方法里super表示当前类的父类
        super.sayHello()
    }
}

let dog=new Dog('小狗',5,'汪汪')
dog.sayHello()
console.log(dog);

抽象类

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

let dog=new Dog('小狗',5)
dog.sayHello()
console.log(dog);

接口

// 描述一个对象类型
type myType={
    name:string,
    age:number
}

const obj:myType={
    name:'sss',
    age:111
}

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

const obj1:myInterface={
    name:'sss',
    age:111,
    gender:'男'
}
/**
 * 接口可以在定义类的时候去限制类的结构
 *    接口中的所有属性都不能有实际的值
 *    接口只定义对象的结构,而不考虑实际的值
 *       在接口中所有的方法都是抽象方法
 */
interface myInter{
    name:string;
    sayHello():void;
}
/**
 * 定义类时,可以使类去实现一个接口
 *    实现接口就是使类满足接口要求
 */
class MyClass implements myInter{
    name:string
    constructor(name:string){
        this.name=name
    }
    sayHello(): void {
        console.log('hello');
    }
}

属性的封装--修饰符

class Person{
    // TS可以在属性前添加属性修饰符
    /**
     * public 修饰的属性可以在任意位置被访问(修改)默认值,子类也可以
     * private 私有属性,私有属性只能在类内部进行访问(修改)
     *     - 通过在类中添加方法使得私有属性可以被外部访问
     *     - 子类不可以
     * protected 受保护的属性,只能在当前类和当前类的子类中访问
     * 
     * 
     */
    name:string;
    age:number;
    private _money:number;

    constructor(name:string,age:number,money:number){
        this.name=name;
        this.age=age;
        this._money=money
    }
    // TS中设置gtter方法的方式
    get money(){
        return this._money
    }
    set money(value:number){
        this._money=value
    }

    // 定义方法获取money属性
    // getMoney(){
    //     return this.money
    // }
    // 定义方法,用来设置money属性
    // setMoney(value:number){
    //     this.money=value
    // }
}

const per = new Person('张三',18,1000000000);
/**
 * 现在属性是在对象中设置的,属性可以任意被修改
 *    属性可以任意被修改将会导致对象中的数据变得非常不安全
 */
per.name='李四'
per.age=-18

class C{
    // 可以将属性直接定义在构造函数中
    constructor(public name:string){}
}
new C('李四')

泛型

/**
 * 在定义函数或者是类时,如果遇到类型不明确就可以使用泛型
 */
function fn<T>(a:T):T{
    return a;
}

// 可以直接调用具有泛型的函数
fn(10);//不指定泛型,TS可以自动对类型进行推断
fn<string>('hello');//指定泛型
// 泛型可以同时指定多个
function fn2<T,K>(a:T,b:K):T{
    return a;
}
fn2<number,string>(123,'')

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

fn3('123')

class MyClass<T>{
    name:T;
    constructor(name:T){
        this.name=name;
    }
}

new MyClass<string>('孙氏')

;