TypeScript学习笔记

310 阅读6分钟

### 1.什么是TS?

TS是JS的超集,JS中有的特性都可以在TS中使用,而且可以使用ES6新特性。但是TS文件不能被JS解析器直接解析,需要通过一个编译过程:tsc <文件名> ——将一个TS文件编译成JS文件。TS的一大特点是变量具有类型。

2.TS语法

1.如何给变量指定类型?

let a:string = 'hello'

如果变量的声明和赋值是同时进行的,那么就可以自动获得这个变量的类型。比如上面的代码不写:string也是可以的。变量指定类型也可以用在函数参数上和返回值上,如下所示:

function add(a:number,b:number):number{
    console.log(a+b)
    return 0
}
add(12,13)

2.字面量的应用场景

//将b的值限定在这三个值的范围之内
let b: 'male' |'female' | 'secret'
console.log(b)

//将b类型限定在这三个值的范围之内
let b: boolean | string | number
console.log(b)

3.新增类型

3.1 any类型

一个变量设置类型为any后,相当于对这个变量关闭了TS的类型检测。

let a:any(显示)

相当于:let a(隐式)

3.2 unknown类型

unknown类型的变量和any类型的变量是及其相似的,都是可以接受任意类型的值,但是不同的是any类型的变量是可以赋值给其他具体类型的变量,导致其他类型的变量的类型检查也会关闭,但是unknown类型的变量是不可以赋值给其他类型变量的。所以用unknown也不用any

3.3 void类型

一般用来设置一个函数的返回值类型,表示函数没有返回值。

3.4 never类型

一般用在报错函数的返回值上,比较鸡肋。

3.5 object

如何规定一个对象中必须有什么属性?

let a:object//用的不是很多,因为对象也有好多子类型,这样写并不能具体到某一个子类型
let b: { name: string}//这就规定了b指向的对象里面有且仅有name
b = {}//报错
b = {
    name:'zh'
}//不报错
//灵活添加属性
let b: { 
    name: string
    age?: number//加了问号代表可选属性
    [propName: string]: any//这样写了以后这个对象中就可以添加任何数量的任意属性
}
b = {
    name:'zh',
    school: 'tjut',
    major: 'xxx'
}

3.6 function

如何规定一个函数的参数类型和返回值类型?

//规定有两个参数,都是number类型,返回值是string类型
let fun: (a:number,b:number)=>string

3.7 array

let e : string[]//规定数组的元素都是string类型
let e: Array<string>//和上面的效果一样

3.8 tuple

固定长度的数组

let a: [string,number]
a=["123",123]

3.9 enum

//定义一个枚举类
enum Gender{
    male,
    female
}
let obj:{
    name:string,
    //gender是Gender类型的,只有两个可选值
    gender:Gender
}
obj = {
    name: 'zh',
    gender: Gender.male
}
export {}

4.编译选项

4.1监视单个文件,当ts文件保存时,自动编译:

tsc <文件名> -w

4.2 监视多个文件

首先创建一个tsconfig.json文件,然后tsc -w命令就可以监视所有的ts文件

4.3 tsconfig.json配置项

{
    //表示那些文件需要被编译,**代表任意文件夹,*代表任意文件
    "include": [
        "./**/*"
    ],
    //与include相反,有些文件不希望被编译
    // "exclude": [
    //     "./2.ts"
    // ]
    //编译器选项,表示如何对ts文件进行编译
    "compilerOptions": {
        //编译成js文件的版本
        "target": "ES3",
        //模块化标准
        "module": "es6",
        //用来指定项目中要是用的库,一般不用设置
        // "lib": []
        //指定编译后的js文件的目录
        "outDir": "./dist",
        //将所有的ts文件的编译成的js文件合并到同一个文件中,用的不多
        // "outFile": "./dist/app.js"
        //是否编译js文件
        "allowJs": false,
        //是否检查js
        "checkJs": false,
        //ts文件的注释是否被转到js文件中
        "removeComments": false,
        //是否生成编译后的js文件
        "noEmit": false,
        //严格检查的总开关
        "strict": true,
        //ts文件有错误的时候是否生成js文件
        "noEmitOnError": true,
        //对编译后的js文件时候使用严格模式
        "alwaysStrict": true,
        //是否禁止使用隐式的any 如函数的参数的类型必须不明确指定的时候就是any
        "noImplicitAny": true,
        //是否禁止隐式的this
        "noImplicitThis": true,
        //是否检查可能为空的值
        "strictNullChecks": true
    }
}

4.4 webpack配置

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const {CleanWebpackPlugin} = require('clean-webpack-plugin')
module.exports = {
    //指定入口文件
    entry: './src/index.ts',
    //编译输出文件的配置
    output:{
        path: path.resolve(__dirname,'dist'),
        filename: 'bundle.js',
        //配置目标文件
        environment:{
            //不允许使用箭头函数
            arrowFunction: false
        }
    },
    //打包时要使用的模块
    module:{
        //指定加载规则
        rules: [
            {
                test: /\.ts$/,
                use: [
                {
                    //指定加载器
                    loader:"babel-loader",
                    //配置babel
                    options:{
                        //设置预定义环境
                        presets: [
                            [
                                "@babel/preset-env",
                                {
                                    //要兼容的目标浏览器
                                    targets:{
                                        "chrome":"88",
                                        "ie":"11"
                                    },
                                    //指定corejs的版本
                                    "corejs":"3",
                                    //使用corejs的方式,按需加载
                                    "useBuiltIns":"usage"
                                }
                            ]
                        ]
                    }
                },
                "ts-loader"
            ],
                exclude: /node-modules/
            }
        ]
    },
    plugins: [
        //指定生成html文件的模板文件的位置
        new HtmlWebpackPlugin(
            {
                template: './src/index.html'
            }
        ),
        //编译的时候首先清空dist文件夹下文件
        new CleanWebpackPlugin()
    ],
    resolve: {
        //规定设么扩展名的文件可以当做一个模块来导入导出
        extensions: ['.ts','.js']
    }
}

5.面向对象

ts中面向对象的知识和Java中面向对象的知识相似。

5.1类

class Person{
    name: string //通过对象实例去访问
    readonly age: number //通过对象实例去访问 readonly表示一个只读的属性
    static school: string = 'tjut' //静态属性通过类名访问
    constructor (name: string,age: number){
        this.name = name,
        this.age = age
    }
    sayHello(){
        console.log('hello ts')
    }//静态方法和静态属性的特定是一样的
}
//new Person()调用的时候相当于调用了构造函数
const p = new Person('zh',18)
console.log(p)//Person { name: 'zh', age: 18 }
console.log(Person.school)//tjut
p.sayHello()//hello ts

5.2 继承、抽象类和接口

继承之后子类拥有父类所有的属性和方法,通过继承我们可以将多个类共有的方法抽取到一个类中。子类和父类中有相同的方法,子类中的方法会覆盖父类中的方法,这就是方法的重写。super关键字就是代表当前类的父类。用抽象类就可以避免用这个类来创建一个对象,比如Animal类,所以抽象类就是用来被继承的。抽象类中可以有抽象方法,抽象方法没有具体实现,只有结构没有方法体,子类必须对抽象方法进行重写。

和抽象类及其相似的一个东西是接口,接口用来定义一个对象中包含哪些属性和方法,也可以当成一个类型来使用。接口中的属性都不能有实际的值,而且所有的方法都是抽象方法。让一个类去实现一个接口,就是让一个类按照接口中的属性和方法类写,接口就是一种规范,对类的一种限制。抽象类中可以有非抽象方法,但是接口中只能有抽象方法。

interface Animal{
    name: string
    age: number
    sayName(): void
}
class Dog implements Animal{
    constructor (public name: string,public age: number){
    }
    sayName(){
        console.log('hahahh')
    }
    sport(){
        console.log('running')
    }
}
const dog = new Dog('旺财',3)
dog.sport()//running

5.3属性修饰符

public 在任何地方都可以修改,这个也是默认值。private 私有只能在类内部修改。protected只能在当前类和当前类的子类中访问

5.4在定义函数或者类的时候,如遇到类型不确定的时候就可以用泛型

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