TypeScript学习笔记

TypeScript学习笔记

1、运行环境(webpack)

1.1、初始化

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

1.2、webpack.config.js

const path = require('path')
const htmlWebpackPlugin = require("html-webpack-plugin")
module.exports = {
    // 指定文件入口
    entry: path.resolve(__dirname, './src/index.ts'),
    // 指定打包文件目录
    output: {
        // 指定打包文件目录
        path: path.resolve(__dirname, './dist'),
        // 指定打包文件名称
        filename: 'bundle.js',
    },
    // 开启source-map,方便调试
    devtool: "inline-source-map",
    // require时可以省略对应的后缀名,如有同名文件,会依次匹配
    resolve: {
        extensions: [".ts", ".js"]
    },
    // 指定打包时要使用得模块
    module: {
        // 指定打包规则
        rules: [
            {
                // 目标文件
                test: /\.ts$/,
                //要使用的loader
                use: {
                    loader: "ts-loader"
                },
                //要排除的文件夹
                exclude: /node_modules/
            }
        ]
    },
    plugins: [
        // 自定义html打包插件
        new htmlWebpackPlugin({
            // 模板文件
            template: "./src/index.html",
            // 输出文件
            filename: "index.html",
        })
    ],
    // 本地开发服务器配置
    devServer: {
        // 文件路径
        static: './dist',
        // 第一次构建是否自动用浏览器打开网页
        open: true,
        // 端口
        port: 9000
    },
    // 模式development|production
    mode: 'development',
    // 指定Webpack构建的环境为web
    target: "web"
}

1.3、tsconfig.json

{
  // 编译选项
  "compilerOptions": {
    // 目标语言的版本
    "target": "ES6",
    // 生成代码的模板标准
    "module": "ES6",
    // 开启所有严格的类型检查
    "strict": true
  }
}

1.4、index.ts

alert("hello world in typescript!")

1.5、index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
Hello World!
<script type="text/javascript" src="../dist/bundle.js" charset="utf-8"></script>
</body>
</html>

1.6、package.json

{
  "name": "typescript",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "webpack-dev-server --open",
    "build": "webpack --mode production"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "html-webpack-plugin": "^5.5.3",
    "ts-loader": "^9.4.4",
    "typescript": "^5.1.6",
    "webpack": "^5.88.1",
    "webpack-cli": "^5.1.4",
    "webpack-dev-server": "^4.15.1"
  }
}

1.7、测试

在这里插入图片描述

2、数据类型

ts类型是在开发的时候检测,编译后不存在类型,ts具有类型推导能力,只有在无法推断或需明确指定才需显式声明类型

  • any、unknow
  • Object
  • Number、String、Boolean(包装类)
  • number、string、boolean
  • 1、‘xumeng03’、true(字面量类型)
  • never(不存在的值)

2.1、any

不进行类型检测,使用如同Js里的变量

let str1: any = 'xumeng03'
let str2: string;
str2 = str1;
let str3: unknown;
str3 = str1;

2.2、unknow

不认为变量为任意一种类型

let str1: unknown = 'xumeng03'
let str2: string;
// 报错
// str2 = str1;
let str3: any;
str3 = str1;

2.3、基础类型

1、number

可以用来表示整数和分数

属性描述
MAX_VALUE最大值
MIN_VALUE最小值
POSITIVE_INFINITY正无穷大
NEGATIVE_INFINITY负无穷大
方法示例描述
toString()把数字转换为字符串,使用本地数字格式顺序
valueOf()返回一个 Number 对象的原始数字值
toPrecision()num.toPrecision(1)把数字格式化为指定的长度(小数点不算)
toFixed()toFixed(1)把数字转换为字符串,并指定位小数点位数
// 数字类型
let age: number = 22;
console.log("数字类型", age);
2、string

''和""可以表示常规字符串,``可以表示插值字符串

属性描述
length字符串的长度
方法描述
charAt()指定位置的字符
charCodeAt()指定的位置的字符的 Unicode 编码
concat()连接两个或更多字符串,返回新的字符串
indexOf()指定的字符串值在字符串中首次出现的位置
lastIndexOf()指定的字符串值在字符串中反向第一次出现的位置
localeCompare()用本地特定的顺序来比较两个字符串;大于0当前字符串大;等于0字符串一样大;小于0当前字符串小
match()查找找到一个或多个正则表达式的匹配
replace()替换与正则表达式匹配的子串
search()检索与正则表达式相匹配的值
split()把字符串分割为子字符串数组
substr(start, length)从起始索引号提取字符串中指定数目的字符
substring(start,stop)提取字符串中两个指定的索引号之间的字符
toLowerCase()转小写
toUpperCase()转大写
// 字符串类型
// @ts-ignore
let name: string = "xumeng03";
console.log("字符串类型", name);
let introduce: string = `my name is ${name}, my age is ${age}`;
console.log("字符串类型", introduce);
3、boolean

值为true/false

// 布尔类型
let isStudent: boolean = false
console.log("布尔类型", "是否学生", isStudent);

2.4、包装类型

1、Number
let a1: Number = Number(1)
let a2: number;
//错误
// a2 = a1;
a2 = a1.valueOf();
2、String
let a1: String = String('xumeng03')
let a2: string;
//错误
// a2 = a1;
a2 = a1.valueOf();
3、Boolean
let a1: Boolean = Boolean(true)
let a2: boolean;
//错误
// a2 = a1;
a2 = a1.valueOf();

2.5、引用类型

1、对象
  • Object:可以包含所有JS类型,一旦赋值无法进行属性新增
  • object:可以包含所有的引用类型(数组类型、对象类型、函数类型)、包装类(Number、String、Boolean),不能包含原始类型
  • {}:如同Object
2、接口

interface通常用于描述类、对象;

基础用法

interface IPerson {
    // 必选属性
    readonly id: number; // 只读属性
    name: string;
    age: number;
    // 可选属性
    address?: string;

    // 索引签名
    [key: string]: any;
}

let zhangsan: IPerson = {
    id: 1,
    name: "zhangsan",
    age: 23,
    // 可选属性
    address: '中国',
    // 索引签名
    tag: [1, 2, 3]
}
// 错误,id是只读属性
// zhangsan.id = 2

接口继承(可多继承)

// 接口
interface IPerson {
    // 必选属性
    id: number;
    name: string;
    age: number;
}

interface Chinese extends IPerson {
    address: string;
}

let zhangsan: Chinese = {
    id: 1,
    name: "zhangsan",
    age: 23,
    // 可选属性
    address: '中国'
}

接口实现

// 接口
interface IPerson {
    // 必选属性
    id: number;
    name: string;
    age: number;
}

class Person implements IPerson {
    id: number;
    name: string;
    age: number;

    constructor(id: number, name: string, age: number) {
        this.id = id;
        this.name = name;
        this.age = age;
    }
}
3、数组
方法描述
concat()连接两个或更多的数组,并返回结果
every()检测数值元素的每个元素是否都符合条件
filter()检测数值元素,并返回符合条件所有元素的数组
forEach()数组每个元素都执行一次回调函数
indexOf()搜索数组中的元素,并返回它所在的位置;如果搜索不到,返回-1
join()把数组的所有元素放入一个字符串
lastIndexOf()返回一个指定的字符串值最后出现的位置
map()通过指定函数处理数组的每个元素,并返回处理后的数组
pop()删除数组的最后一个元素并返回删除的元素
push()向数组的末尾添加一个或更多元素,并返回新的长度
reduce()将数组元素计算为一个值(从左到右)
reverse()反转数组的元素顺序返回一个字符串
shift()删除数组并返回数组的第一个元素
unshift()向数组的开头添加一个或更新元素,并返回新的长度
slice(start, stop)选取数组的的一部分,并返回一个新数组
some()检测数组元素中是否有元素符合指定条件
sort()对数组的元素进行排序
splice(start, removeLength, addStr)从数组中添加或删除元素
toString()把数组转换为字符串,并返回结果
// 数组类型
let hobby: string[] = ['book', 'code']
// let hobby: Array<string> = ['book', 'code']
console.log("数组类型", hobby);
let code: (string | number)[] = [1, 'java']
console.log("数组类型", code);
// 多维数组
let books: [string[], number[]] = [['book', 'code'], [1, 2]]
// IArguments
function a(...args: any[]) {
    let a: IArguments = arguments
    console.log(a)
}
a(1,2,2,3,3,3,3,3,3,3,2)
4、元组
// 元组类型
let userinfo: [string, number, boolean] = ['zhangsan', 23, false]
console.log("元组类型", userinfo);
5、函数
// 函数定义
let fun1 = function (a: string, b: string): string {
    return a + b;
}
let fun2 = (a: string, b: string): string => {
    return a + b;
}
// 可选参数
type Fun3 = (a: string, b: string, c?: string) => string
let fun3: Fun3 = (a, b, c): string => {
    return a + b;
}
console.log(fun2('1', '2'));
console.log(fun3('1', '2', '3'));
// 默认值(不可与可选参数一起用)
type Fun4 = (a: string, b: string) => string
let fun4 = (a = 'abc', b: string = 'def'): string => {
    return a + b;
}
console.log(fun4());
// 函数重载
function fun5(a: string): string;
function fun5(a: number): number;
function fun5(a: string | number): string | number {
    return a;
}
6、枚举
// 枚举,推荐使用常量枚举,不会额外生成对象
enum ROLE {
    Student,
    Teacher,
    ADMIN
}

console.log("枚举类型", ROLE.ADMIN, ROLE[0]);

const enum ROLE1 {
    Student,
    Teacher,
    ADMIN
}

console.log("枚举类型", ROLE1.ADMIN);

const enum ROLE2 {
    Student = 1,
    Teacher = 5,
    ADMIN
}

console.log("枚举类型", ROLE2.ADMIN);

const enum ROLE3 {
    Student = 'a',
    Teacher = 'b',
    ADMIN = 'c'
}

console.log("枚举类型", ROLE3.ADMIN);
console.log("枚举类型", ROLE[0]);
// 数字枚举可以反向映射,字符串枚举不行
// console.log("枚举类型", ROLE3['a']);
7、类
// 类
class Person {
    // 实例属性(修饰符public、protected、private)
    name: string = 'xumeng';
    age: number = 22;
    // 实例私有属性
    private _id: number = 1
    // 实例只读属性
    readonly _type: string = '多细胞生物'

    get getId() {
        return this._id
    }

    set setId(id: number) {
        this._id = id
    }

    // 静态属性
    static type: string = '人类'

    // 构造方法
    constructor(name: string, age: number, world: (...args: any[]) => any) {
        this.name = name
        this.age = age
        this.world = world
    }

    // 原型方法
    hello() {
        return "hello!"
    }
    // 实例方法
    world: () => "";
}

// 实例
let person = new Person("xumeng03", 22, () => "world");
console.log(person, person.getId, Person.type, person.hello(), person.world());

// 继承
class Chinese extends Person {
    address: string = '中国';

    constructor(name: string, age: number, address: string) {
        super(name, age, () => "world")
        this.address = address
    }

    hello() {
        return "你好世界!"
    }
}
let chinese = new Chinese("xumeng03", 22, '上海')

// 判断对象是否是目标类的实例
console.log(chinese instanceof Person);
8、抽象类
// 抽象类
abstract class Animal {
    // 实例属性
    abstract name: string;
    // 实例方法
    abstract eat: () => string;
    // 原型方法
    abstract speak(): string;
}

class Cat extends Animal {
    name: string = 'cat';

    constructor() {
        super();
        this.eat = () => ""
    }

    eat: () => "";

    speak(): string {
        return "miao~";
    }
}

let cat = new Cat()
console.log(cat);

2.6、联合类型&交叉类型

1、联合类型

两者满足任意一个即可

let strOrNum: string | number='abc';
strOrNum = 1
2、交叉类型

需同时满足两者

class Person1 {
    id: number

    constructor(id: number) {
        this.id = id
    }
}

class Person2 {
    name: string

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

let person: Person1 & Person2 = {
    id: 1,
    name: "xumeng03"
}

2.7、内置对象

let date: Date = new Date();
let reg: RegExp = new RegExp(/\w/);
let err: Error = new Error("Error");
let xhr: XMLHttpRequest = new XMLHttpRequest();
let html1: HTMLHtmlElement | null = document.querySelector('html')
let input1: HTMLInputElement | null = document.querySelector('input')
let div1: NodeList = document.querySelectorAll('div')
let div2: NodeListOf<HTMLElement | HTMLDivElement> = document.querySelectorAll('div')
let storage:Storage = localStorage

2.8、特殊类型

1、null、undefined

null表示对象值缺失,undefined表示初始化变量为一个未定义的值,严格模式(默认模式)不可混用

// null类型、undefined类型
let a: null = null
console.log("null类型", a);
let b: undefined = undefined
console.log("undefined类型", b);
2、void

常用于函数的返回值

// void类型
function hello(): void {
    alert("hello world");
}
hello()
3、never

是所有类型(包括 null 和 undefined)的子类型,表示从不会出现的值/无终点

type A = 'code' | 'write'
// 新增属性会导致TheType函数报错,可以起到逻辑完整性检测的作用
// type A = 'code' | 'write' | 'read'

function TheType(type: A) {
    switch (type) {
        case "code":
            console.log("code");
            break
        case "write":
            console.log("write");
            break
        default:
            const theType: never = type
            break
    }
}
4、symbol
let a1: symbol = Symbol(1)
let a2: symbol = Symbol(1)
// Symbol.for会寻找有没有当前key,如果有直接用
console.log(a1, a2, a1 === a2, Symbol.for('xumeng03') === Symbol.for('xumeng03'))

let a = {
    id: 1,
    [a1]: 1,
    [a2]: 2,
}
// 获取所有属性值(string/symbol)
console.log(Reflect.ownKeys(a));

// 生成器(灵活的控制函数的暂停执行)
function* progress() {
    yield 33
    yield 66
    return 99.9
}

const generator = progress()
console.log(generator.next())
console.log(generator.next())
console.log(generator.next())

// 生成器(分段传参)
function* progress1(num: number) {
    let result = 0
    console.log(num, result)
    // 第一个next在此处卡住
    result = yield num + result;
    console.log(num, result)
    // 第二个next在此处卡住,第三个next从此处继续执行
    result = yield num + result;
    console.log(num, result)
}

const generator1 = progress1(1)
console.log(generator1.next())
console.log(generator1.next(2))
console.log(generator1.next(3))

// 迭代器,可迭代对象(string、array、Set、NodeList、Arguments、Map)
// string
let str = 'xumeng03'
for( let text of str) {
    console.log(text) //字符串每个遍历打印
}
// 数组
const bears = ['book', 'code', 'game']
for( let bear of bears) {
    console.log(bear)
}

2.8、类型断言

function ilength(str: string | number) {
    return (str as string).length;
}

console.log(ilength('abc'));
console.log(ilength(123));

let strOrNum: string | number;
console.log("类型断言", (strOrNum! as string).includes("a"));
console.log("类型断言", (<string>strOrNum!).includes("a"));

2.9、自定义类型

type通常用于描述函数签名、联合类型、工具类型、映射条件类型;

// 自定义类型
type Direction = 'up' | 'down'
let abc: Direction;
abc = 'up'

type s1 = string
type s2 = string | number
type s3 = () => string

2.10、内置工具类型

1、Record
type k = 1 | 2 | 3

interface Student {
    name: string;
    age: number;
}

const p: Record<number, Student> = {
    1: {
        name: 'xumeng01',
        age: 20
    },
    2: {
        name: 'xumeng02',
        age: 20
    },
    3: {
        name: 'xumeng03',
        age: 20
    },
}
2、Partial

让传入类型中的所有属性变成都是可选的

interface Student {
    name: string;
    age: number;
}
// 报错,name、age为必选属性
// const student1: Student = {}

const student2: Partial<Student> = {}
3、Required

让传入类型中的所有属性变成都是必选的

interface Student {
    name?: string;
    age?: number;
}

const student1: Student = {}
// 报错,name、age为必选属性
// const student2: Required<Student> = {}
4、Readonly

让传入类型中的所有属性变成都是只读的

interface Student {
    name: string;
    age: number;
}

const student1: Student = {
    name: 'xumeng02',
    age: 20
}
student1.age = 21

const student2: Readonly<Student> = {
    name: 'xumeng03',
    age: 20
}
// 报错,属性age只读
// student2.age = 21
5、Pick

选择传入类型中的部分属性组成新类型

interface Student {
    name: string;
    age: number;
}

const student1: Student = {
    name: 'xumeng01',
    age: 20
}

const student2: Pick<Student, 'name'> = {
    name: 'xumeng02'
}

const student3: Pick<Student, 'name'> = {
    name: 'xumeng03',
    // 报错,Pick<Student, 'name'>没有age属性
    // age: 20
}

const student4: Pick<Student, 'name' | 'age'> = {
    name: 'xumeng04',
    age: 20
}
6、Exclude

针对联合类型,排除相同的,留下不同的

type PersonAttr = 'name' | 'age'
type StudentAttr = 'name' | 'age' | 'class' | 'school'

const student1: Exclude<StudentAttr, PersonAttr> = 'class'
7、Extract

针对联合类型,排除不同的,留下相同的

type PersonAttr = 'name' | 'age'
type StudentAttr = 'name' | 'age' | 'class' | 'school'

const student1: Extract<StudentAttr, PersonAttr> = 'name'
8、Omit

传入一个类型,和这个类型的几个属性,把传入的属性省略掉,组成一个新类型

interface Student {
    name: string;
    age: number;
    class: string;
    school: string;
}

export type PersonAttr = 'name' | 'age'

const student1: Omit<Student, PersonAttr> = {
    class: '',
    school: ''
}
9、NonNullable

不能为空

type k = string | null | undefined
// 报错,不能为空
// let p: NonNullable<k> = null
// 报错,不能为空
// let p: NonNullable<k> = undefined
10、Parameters

获取传入函数的参数组成的元组类型

interface StudentFunc {
    (name: string, age: number): string
}

const student1: Parameters<StudentFunc> = ['xumeng03', 22]

11、ConstructorParameters

获取传入构造函数的参数组成的元组类型

class Student {
    name: string;
    age: number;
}

const student1: ConstructorParameters<new (name: string, age: number) => Student> = ['xumeng03', 22]
12、ReturnType

获取传入函数的返回类型

class Student {
    name: string;
    age: number;
}

const student1: ReturnType<(name: string, age: number) => Student> = {
    name: 'xumeng03',
    age: 22
}
13、InstanceType

获取传入构造函数的返回类型

class Student {
    name: string;
    age: number;

    constructor(name: string, age: number) {
        this.name = name
        this.age = age
    }
}

const student1: InstanceType<typeof Student> = {
    name: 'xumeng03',
    age: 22
}
14、Uppercase
type StudentSexType = 'male' | 'female'

const studentSex: Uppercase<StudentSexType> = 'MALE'
15、Lowercase
type StudentSexType = 'MALE' | 'FEMALE'

const studentSex: Lowercase<StudentSexType> = ''
16、Capitalize
type StudentSexType = 'male' | 'female'

const studentSex: Capitalize<StudentSexType> = ''
17、Uncapitalize
type StudentSexType = 'MALE' | 'FEMALE'

const studentSex: Uncapitalize<StudentSexType> = ''

2.11、infer

1、类型推断
type k<T> = T extends Array<infer U> ? U : T
const a: k<string[]> = 'xumeng03'
2、类型提取
type arr = ['a', 'b', 'c']

type p1<T extends any[]> = T extends [infer U, ...any[]] ? U : [];
type p2<T extends any[]> = T extends [...infer U, infer K] ? U : [];

const b1: p1<arr> = 'a'
const b2: p2<arr> = ['a', 'b']
3、递归
type arr = ['a', 'b', 'c']

type rever<T extends any[]> = T extends [infer f, ...infer rest] ? [...rever<rest>, f] : T;
const a: rever<arr> = ['c', 'b', 'a']

3、泛型

3.1、定义

// 接口中使用泛型
interface fun4<T> {
    id: T
}

let data1: fun4<number> = {
    id: 1
}

// 方法中使用泛型
const fun2 = function <T>(param: T): T {
    return param
}

console.log(fun2<number>(1));
console.log(fun2<string>("xumeng03"));

// type中使用泛型
type IFun = <T>(param: T) => T
const fun3: IFun = (param) => {
    return param
}

console.log(fun3<number>(1));
console.log(fun3<string>("xumeng03"));

3.2、泛型默认值

const fun4 = <T = string>(param: T): T => {
    return param
}
console.log(fun4("xumeng03"));

3.3、泛型约束

// 泛型约束
const fun5 = function <T extends number>(param1: T, param2: T) {
    return param1 + param2;
}
console.log(fun5<number>(1, 1));
// console.log(fun5<string>("xumeng03","22"));

type I1 = {
    age: number
}
const fun6 = function <T extends I1>(param: T): number {
    return param.age
}

type I2 = {
    name: string
    age: number
}
const fun7 = function <T extends I2, U extends keyof I2>(param: T, key: U): T[U] {
    return param[key]
}
console.log(fun7({name: "xumeng03", age: 23}, "name"));
console.log(fun7({name: "xumeng03", age: 23}, "age"));

type I3<T extends I2, U extends keyof I2> = T[U]
const fun8 = function <T extends I2, U extends keyof I2>(param: T, key: U): I3<T, U> {
    return param[key]
}

3.4、泛型抽离

type I3<T extends I2, U extends keyof I2> = T[U]

const fun8 = function <T extends I2, U extends keyof I2>(param: T, key: U): I3<T, U> {
    return param[key]
}

3.5、条件分发

type Code<T> = T extends 200 | 201 ? true : false
type icode1 = Code<200>
type icode2 = Code<201>

type Code1<T, U> = T extends U ? true : false
type icode3 = Code1<201, number>
type icode4 = Code1<201, string>

type I4<T> = T extends number ? number : string;
const fun9 = function <T extends number | string>(param1: T, param2: T): I4<T> {
    return param1 + (param2 as any);
}

type I5<T> = T extends number ? number : string;
// 涉及到泛型时会进行类型分发(string | number)
type type1 = I5<string | number>
// 直接使用不会进行类型分发(string)
type type2 = (string | number) extends number ? number : string;

避免条件分发

// 避免条件分发
type I6<T> = T & {};
type type3 = I6<string | number> extends number ? number : string;

判断条件分发是否相等

// 判断条件分发是否相等
type I7<T, U> = T extends U ? U extends T ? true : false : false;
type type4 = I7<string, number>
type type5 = I7<string, string>

获取两个类型交集

// 获取两个类型交集
type I8 = Extract<string | number, string>

排除两个类型交集

// 排除两个类型交集
type I9 = Exclude<string | number, string>

判断非空

let e = document.getElementById("app")
type I10 = NonNullable<typeof e>

3.6、类型推断

// 类型推断
function fun1(param1: string, param2: number) {
    return {param1, param2}
}

type t1 = typeof fun1;
// type ReturnType<T> = T extends (param1: string, param2: number) => infer R ? R : never;
// type ReturnType<T> = T extends (...args: any) => infer R ? R : never;
type t2 = ReturnType<typeof fun1>;

function fun2(param1: string, param2: number) {
    return {param1, param2}
}
type ReturnType1<T extends (...args: any) => any> = T extends (...args: infer R) => any ? R : never;
type t3 = ReturnType1<typeof fun1>;

4、命名空间

在最新的TypeScript版本中,推荐使用ES模块(ES Modules)作为模块化的解决方案,而不是过度使用命名空间

// 命名空间
namespace Zoo {
    export let name: string
    export class Dog{}
}
console.log(Zoo.name, Zoo.Dog)

namespace Home {
    export let name: string
    export class Dog{}
}
console.log(Home.name, Home.Dog)

5、tsconfig.json

{
  // 编译选项
  "compilerOptions": {
    // 编译时会生成一个缓存文件,第二次编译会读取缓存文件,加快编译速度
    "incremental": true,
    // 缓存文件位置
    "tsBuildInfoFile": ".tsbuildinfo",
    // 打印编译信息
    "diagnostics": false,
    // 目标语言的版本
    "target": "ES6",
    // 生成代码的·模板·标准
    "module": "ES6",
    // ts使用的库
    // "lib": [],
    // 允许编译js
    // "allowJs": false,
    // 允许js报错,一般与allowJs一起使用
    // "checkJs": false,
    // 指定输出目录
    "outDir": "./dist",
    // 指定文件目录
    "rootDir": "./",
    // 自动生成声明文件
    "declaration": true,
    // 指定生成文件位置
    "declarationDir": "",
    // 生成声明文件的sourcemap
    "declarationMap": false,
    // 生成目标文件的sourcemap
    "sourceMap": false,
    "inlineSourceMap": false,
    // 第三方声明文件的放置位置
    "typeRoots": [],
    "types": [],
    // 删除注释
    "removeComments": true,
    // 编译后不产生js文件
    "noEmit": false,
    // 编译发生错误不会输出js文件
    "noEmitOnError": true,
    // 遍历器降级
    "downlevelIteration": false,
    // 开启所有严格的类型检查
    "strict": true,
    // 严格模式下为文件头部注入"use strict"
    "alwaysStrict": true,
    // 不允许隐式的any
    "noImplicitAny": true,
    // 不允许把null、undefined赋值给其他变量
    "strictNullChecks": true,
    // 不允许函数双向协变
    "strictFunctionTypes": false,
    // 类的实例属性必须初始化
    "strictPropertyInitialization": false,
    // 严格检查Bind、Call、Apply类型
    "strictBindCallApply": true,
    // 不允许this有隐式的any类型
    "noImplicitThis": false,
    // 检查未使用的局部变量
    "noUnusedLocals": false,
    // 检查未使用的函数参数
    "noUnusedParameters": false,
    // 放置switch语句贯穿(没有break)
    "noFallthroughCasesInSwitch": false,
    // 模块编译策略
    "moduleResolution": "classic",
    // 解析非相对模块的基地址
    "baseUrl": "./",
    // js语法的解析器
    "jsxFactory": "React.createElement",
    // jsx解析器
    "jsx": "preserve",
    // 路径映射
    "paths": {
      // 手动指定json5版本
      "@json5": [
        "node_modules/json5/dist/index.min.js"
      ]
    }
  },
  // 指定编译目录
  "include": [
    "src/**/*"
  ],
  // 编译排除目录
  "exclude": [],
  // 指定文件使用该配置
  "files": []
}

6、声明文件

常用于第三方库没有声明文件时时候

declare const xumeng: string;

7、装饰器

tsconfig中compilerOptions的experimentalDecorators需要设置为true

  • 装饰器的执行时机,不是在创建实例的时候运行,而是在类创建的时候就会执行

  • 装饰器对类的行为的改变,是代码编译时发生的,而不是在运行时。这意味着,装饰器能在编译阶段运行代码

7.1、类装饰器

// 类装饰器
const Xuehua: ClassDecorator = (target) => {
    // target代表class Xue
    console.log(target);
    target.prototype.name = "xumeng03"
    target.prototype.helloworld = () => {
        return "hello world!"
    }
}

@Xuehua
class Xue {
    constructor () {
    }
    // ......
}

const xue = new Xue() as any
console.log(xue.name,xue.helloworld())

7.2、装饰器工厂

// 装饰器工厂
const Fun = (name: string): ClassDecorator => {
    return (target) => {
        // target代表class Xue
        console.log(target);
        target.prototype.name = name
        target.prototype.helloworld = () => {
            return "hello " + name + '!';
        }
    }
}

@Fun("xumeng03")
class Xue {
    constructor() {
    }

    // ......
}

const xue = new Xue() as any
console.log(xue.name, xue.helloworld())

7.3、多装饰器

// 装饰器工厂
const Fun = (name: string): ClassDecorator => {
    return (target) => {
        // target代表class Xue
        console.log(target);
        target.prototype.name = name
        target.prototype.helloworld = () => {
            console.log("hello " + name + '!')
        }
    }
}
const Fun2 = (name: string): ClassDecorator => {
    return (target) => {
        // target代表class Xue
        console.log(target);
        target.prototype.name1 = name
        target.prototype.helloworld1 = () => {
            console.log("hello " + name + '!')
        }
    }
}

// 执行顺序由下到上
@Fun("xumeng03")
@Fun2("xumeng")
class Xue {
    constructor() {
    }

    // ......
}

const xue = new Xue() as any

7.4、函数装饰器

const Fun = (name: string): MethodDecorator => {
    return (target, key, descriptor: PropertyDescriptor) => {
        // target代表class Xue
        console.log(target, key, descriptor, name);
        // ......
        descriptor.value(name)
    }
}

class Xue {
    constructor() {

    }

    @Fun("xumeng03")
    getName(data: string): void {
        console.log('hello ' + data + '!')
    }
}

const xue = new Xue();

7.5、参数装饰器

待补。。。

7.6、属性装饰器

待补。。。

8、逆变&协变&双向协变

// 协变(变量)
class Biology {
    id: number
}
class Person extends Biology {
    name: string
}
let b: Biology
let p: Person = {
    id: 2,
    name: "xumeng03"
}
b = p

// 逆变(函数)
let b1 = (param1: Biology) => {
}
let p1 = (param1: Person) => {
}
// 报错
// b1=p1
p1=b1

// 双向协变(tsconfig中compilerOptions的strictFunctionTypes需要设置为false)
let b1 = (param1: Biology) => {
}
let p1 = (param1: Person) => {
}
// 不再报错
b1=p1
p1=b1
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

眼眸流转

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值