【简洁易学】TypeScript 学习笔记

news/2024/12/22 19:07:26/

文章目录

  • TypeScript学习笔记
    • 一、TS简介
      • 1. 学习前提
      • 2. TypeScript是什么?
      • 3. TypeScript增加了什么?
    • 二、TS开发环境搭建
      • 1. 下载、安装Node.js
      • 2. npm安装TypeScript
      • 3. 创建一个TS文件,使用tsc对TS文件进行编译
    • 三、TS的类型
      • 1. 类型声明
      • 2. 类型大全
        • 2.1 字面量
        • 2.2 any / unknown
        • 2.3 void / never
        • 2.4 object
        • 2.5 array
        • 2.6 tuple
        • 2.7 enum
        • 2.8 其它
    • 四、编译选项
      • 1. 监视
      • 2. tsconfig.json
      • 3. 配置选项
        • 3.1 include / exclude
        • 3.2 extends files
        • 3.3 CompilerOptions【重要】
          • 3.3.1 target
          • 3.3.2 module
          • 3.3.3 lib
          • 3.3.4 outDir outFile
          • 3.3.5 allowJs checkJs
          • 3.3.5 removeComments noEmit noEmitError
          • 3.3.6 alawaysStrict noImplicitAny noImplicitThis
          • 3.3.7 strictNullChecks strict
    • 五、webpack打包ts代码
      • 1.初始化项目:
      • 2. 下载构建工具
      • 3.创建`webpack.config.js`并编写
      • 4. tsconfig.json文件配置
      • 5. 补充
    • 六、面向对象
      • 1. 类class
      • 2. 构造函数和this
      • 3. 继承
      • 4. 抽象类
      • 5. 接口
      • 6. 属性的封装
      • 7. 泛型
    • 总结

TypeScript学习笔记

一、TS简介

1. 学习前提

学习前端必备语言javascript,它易学易用,开发过程中挖坑也容易(/狗头),维护起来比较难受,不太适合开发大型项目。

JS变量是一个动态类型,比如说let a = 123,后面也可以给a赋值为字符串、布尔值等等。

JS函数的参数没有类型限制,很自由也不报错,容易挖坑。

JS很好,但是也存在一些缺点让人头痛。

我们希望有一个新的语言,来弥补一些缺点,而不是替代JS。微软设计的TypeScript就很不错。

2. TypeScript是什么?

TS是以 JS 为基础构建的语言,是 JS 的一个超集

TS 扩展了 JS 并添加了类型,可以在支持JS的平台上执行。可能你在书写 TS 的时候觉得它事儿多,但是习惯之后会觉察出它的优势的,坚持下去。

TS 目前不能被 JS 解析器直接执行,我们要将 TS 编译成 JS 执行。

3. TypeScript增加了什么?

大体列举一下,后续会进行学习,不着急不着急

  • 类型
  • 支持ES的新特性
  • 添加ES不具备的新特性
  • 丰富的配置选项
  • 强大的开发工具

二、TS开发环境搭建

1. 下载、安装Node.js

系统最好是64位的因为这样内存会大一些。

node.js官网下载即可,用LTS这种长期维护版本,安装路径尽量不要有特殊符号和中文。

查看node版本命令:node -v

2. npm安装TypeScript

查看npm版本命令:npm -v

npm安装TS : npm i -g typescript,会有点慢,呆胶布,我会等。
在这里插入图片描述

检查:输入tsc,出现一堆乱七八糟,说明OK了

在这里插入图片描述

3. 创建一个TS文件,使用tsc对TS文件进行编译

推荐的是VSCode编辑器书写代码

在这里插入图片描述

我们都知道编辑器它不认ts文件呢,现在我们用**tsc编译器**编译一下,目录下会生成一个js文件
在这里插入图片描述

网页中引入js文件就可以执行了

三、TS的类型

1. 类型声明

TS 和 JS 的一个区别就是 TS 的变量有类型的概念

在 js 里我们可以给变量 a 任意赋值,可能给后期维护挖了大坑

let a;
a = 'hello';
a = 2;

那我们在TS中怎么做呢?

//声明一个变量,同时指定它的类型为number数字,
let a:number
a = 1 ; //不报错
a = ''  //报错

此时 a 只能赋值数字,要是赋值其他的类型将会报错
在这里插入图片描述

声明完变量直接赋值:

let c:boolean = true  //如果声明和赋值同时进行,那TS可以自动对变量进行类型检测
let c = false         //可以这样简写

函数参数类型:

function sum(a:number,b:number){return a + b
}
sum(a:123,b:'123')  //此时 b 会报错,相比于 js 能让人更好的发现问题从而进行修改,参数要是传多了也会报错。

返回值类型:

function sum(a:number,b:number):number{return a + b
}
let result = sum(a:123,b:'123')  

== ts 可以编译成任意版本的 js ,可以对编译器进行配置,来决定编译成哪种版本,后面会学习到==

要是想演示一下看效果,可以创建一个index.html文件,将js文件引入到html文件里面,运行html文件即可。

ts 代码改完了记得进行编译:tsc 文件名

小结:

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

2. 类型大全

类型描述
number任意数字
string任意字符串
boolean布尔值
字面量限制变量的值就是该字面量的值
any任意类型
unknown类型安全的any
void没有值或undefined
never不能是任何值
object任意的 JS 对象
array任意 JS 数组
tuple元素,TS 新增类型,固定长度的数组
enum枚举,TS 中新增类型
2.1 字面量

可以使用字面量进行类型声明

let a:number = 10;  //原写法
let a:10;    //使用字面量进行类型声明,说明a是number类型,但是这时a的值就固定了
a = 11;   //报错

一般这样用:

联合类型常用

// |表示或,用来连接多个类型(联合类型)
let b:string | boolean
b = true  //不报错
b = 'hello'  //不报错let a: 10 | 11   
a = 10  //不报错
a = 11 //不报错
a = 12  //报错
2.2 any / unknown

表示任意类型,设置any类型后对该变量关闭类型检测,不建议使用any

声明变量不指定类型,则TS解析器自动判断变量的类型为any(隐式any

let c:any;
//均不报错
c = false
c = 'hello'
c = 123

如果实在不知道变量d的类型,那我们可以使用unknown

unknown实际上是一个类型安全的any。

//unknown 表示未知类型
//均不报错
let d : unknown;
d = 123
d = 'hello'
d = true

=c 的类型是any,可以赋值给任意变量;unknow类型的变量d赋值给其他类型的变量会报错=

s = 'ruru'
s = c;  //不报错
s = d;  //报错,这种情况可以处理

处理办法

  1. 判断
if (typeof d === 'string') {s = d;
}
  1. 类型断言
/*
*语法:
*   变量 as 类型
*   <类型>变量
**/
s = d as string;
s = <string>d;
2.3 void / never

设置函数返回值用的多

void表示为空

没有返回值,类型设置为void,没写类型默认是void

function fn():void{
}

never表示永远不会返回结果

function fn2():never{throw new Error('报错了')
}
2.4 object

在js中一切皆对象

//object表示一个对象,这种写法不常用
let a: object;
a = {};
a = function () { };

语法:{属性名:属性值 , 属性名:属性值}

{}指定对象中可以包含哪些属性

//这种常用
//?表示可选属性
let b: { name: string, age?: number };
b = { name: '孙' }
b = { name: '孙', age: 18 }

优化一下:

//?表示可选属性
//[propName: string]: any 表示任意类型的属性
let b: { name: string, [propName: string]: any };
b = { name: '孙' }
b = { name: '孙', age: 18, a: 1, b: 2 }

函数

设置函数结构的类型声明

语法:(形参:类型,形参:类型) => 返回值

//没啥意义,我们是希望来限制它的结构
let f:Function

这样写:希望函数f的参数类型都是number,返回值也是number

let f:(a:number,b:number) => number
f = function(n1,n2){return n1 + n2
}

语法学习无捷径,多写多做是良训。

2.5 array

开发中数组中存储一种类型的值。

语法:类型[ ] or Array<类型>

let e: string[];
let x: Array<string>;
let z: number[];
e = ['a','b',1]  //报错,因为里面有数字和字符串两种类型
x = ['1','2','3']
z = [1,2,3]
2.6 tuple

元组类型,TS新增,固定长度的数组

语法:[类型,类型,…]

let v: [string, string];
v = ['h', 'h']
v = ['a','a','a']   //报错
2.7 enum

枚举,TS新增,把可能情况都列出来

enum Gender {//定义一个枚举的类Male,Female
}let i: { name: string, age: number, gender: number }
i = {name: '孙悟空',age: 500,gender: 1
}
console.log(i.gender = Gender.Male)
2.8 其它
  • &与
let t = {name:String}& {age:number}  //这代表对象t要同时有这两种属性
  • 类型的别名

1 | 2 | 3 | 4起个别名,很方便,简化类型的使用。

type myType = 1 | 2 | 3 | 4
let a: myType;
let b: myType;
let c : myType;

四、编译选项

1. 监视

TS写完之后需要编译才能执行。

新建一个TS文件,我们编写一段代码,运行 tsc 文件名 进行编译。

每当修改ts文件时都要一遍遍重新编译,忒麻烦,我们使用监视器监视我们这段代码,每当代码发生变化时就重新编译代码,不需要手动操作了。

有个时间间隔,需要等待一下

tsc 文件名 -w  

在这里插入图片描述

只针对于单一文件,需要每个文件都配置。不太适合日常开发。ctrl c退出监视。

2. tsconfig.json

在目录下创建一个tsconfig.json文件,对tsc进行配置.
在这里插入图片描述

这时命令行输入 tsc就可以编译文件里所有的TS文件了。

tsc -w 监视的是所有的TS文件

tsconfig.json是ts编译器的配置文件,ts编译器可以根据它的信息来对代码进行编译。

3. 配置选项

3.1 include / exclude

这两个直接写在大括号里

include:用来指定哪些ts文件需要被编译

    "include": [// 表示src目录下的任意文件夹下的任意文件都能被执行"./src/**/*"]

exclude:指定不需要编译的,默认值"node_modules","bower_components","jspm_packages"

 "exclude": [//表示src目录下的app.ts不需要被编译"./src/app2.ts"]
3.2 extends files

这两个直接写在大括号里

extends:定义被继承的配置文件

//当前配置文件会自动包含config目录下base.json中的所有配置信息"extends":"./config/base"

files:指定被编译文件的列表,文件少可能才会用到

"files":["app.ts","app2.ts",...
]
3.3 CompilerOptions【重要】

编译器选项,稍微麻烦一些,且看下面详解

3.3.1 target

指定TS被编译为的ES版本,默认ES3版本

可选:'ES3' , 'ES5' , 'ES2016' , 'ES2017' , 'ES2018' , 'ES2019' , 'ES2020'

例如转成ES6版本,esnext代表的是ES最新版本

"CompilerOptions": {"target": "es6"}
3.3.2 module

指定使用的模块化的规范

可选:none,commonjs,and,system,umd,es6

"CompilerOptions": {"target": "ES6","module": "commonjs"}
3.3.3 lib

指定项目中用到的库,一般情况不需要改。

只要是在浏览器中运行一般不需要管,在node.js中执行根据实际情况修改。

 "CompilerOptions": {"target": "ES6","module": "commonjs",//"lib": [//   "dom"// ]}
3.3.4 outDir outFile

outDir:指定编译后文件所在目录

outFile:代码合并为一个文件, 全局作用域中的代码会合并到同一个文件中,用的不多,了解一下。

"CompilerOptions": {"target": "ES6","module": "commonjs",// "lib": [//    "dom"//],"outDir": "./dist","outFile": "./dist/app.js"}
3.3.5 allowJs checkJs

checkJs:是否对js文件进行编译,默认是false

checkJs:检查js代码是否符合js代码规范,默认值false

"allowJs": true,
"checkJs": true
3.3.5 removeComments noEmit noEmitError

removeComments: 是否移除注释

"removeComments":true

noEmit: 不生成编译后的文件

"noEmit":true

noEmitError有错误时不生成编译后的文件

"noEmitError": true
3.3.6 alawaysStrict noImplicitAny noImplicitThis

alawaysStrict : 指定编译后的文件是否使用严格模式

"alwaysStrict":true

noImplicitAny: 不允许隐式的any类型

"noImplicitAny": true

noImplicitThis: 不允许不明确类型的this

"noImplicitThis":false
3.3.7 strictNullChecks strict

strictNullChecks :严格检查空值

"strictNullChecks":true

box1不存在也没有报错,当设置了strictNullChecks时,会报错“box1可能为空”

let box1 = document.getElementById('box1');
box1.addEventListener('click', function () {alert('hello');
})

解决办法:可以使用if判断是否为空。

strict:总开关,开发建议设为true

综上

以上是比较常用的,其他的用到现查。

五、webpack打包ts代码

1.初始化项目:

生成一个package.json

npm init -y

2. 下载构建工具

npm i -D webpack webpack-cli ts-loader typescript 

3.创建webpack.config.js并编写

//引入一个包
const path = require('path');//webpack配置信息都写在module.exports里面
module.exports = {//指定入口文件,在文件中新添加一个index.tsentry: './src/index.ts',//指定打包文件output: {path: path.resolve(__dirname, "dist"),//打包好文件的文件filename: 'bundle.js'},//指定webpack打包时要使用的模块module: {//指定要加载的规则rules: [{//test:规则生效的文件//用ts-loader处理ts结尾的文件test: /\.ts$/,use: 'ts-loader',  //要使用的loaderexclude: /node-modules/  //要排除的文件}]}
}

4. tsconfig.json文件配置

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

打包,在package.json中添加一行命令"build":"webpack
在这里插入图片描述

执行webpack,对文件进行打包

npm run build

出现一个dist文件夹,就成功了!

5. 补充

自动生成html文件,自动引入js文件

安装插件:

npm i -D html-webpack-plugin  //帮助我们自动生成html文件

webpack.config.js里引入并编写代码

const HTMLWebpackPlugin = require('html-webpack-plugin')//配置webpack插件,plugins: [new HTMLWebpackPlugin({
//          title:'ruru'  //自定义titletemplate:"文件地址"  //写好一个文件,作为生成html文件的模板});]

在浏览器中访问网页,自动刷新

安装插件

npm i -D webpack-dev-server

package.json配置:"start": "webpack serve --open chrome.exe"

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

启动项目成功会自动打开浏览器。可以实时更新

编译前dist目录清空

安装插件

npm i -D clean-webpack-plugin

和那个html用法一样

const {CleanWebpackPlugin} = require('clean-webpack-plugin')//配置webpack插件,plugins: [new CleanWebpackPlugin(),new HTMLWebpackPlugin({
//          title:'ruru'  //自定义titletemplate:"文件地址"  //写好一个文件,作为生成html文件的模板});]

告诉webpack哪些模块可以被引入

webpack.config.js中设置

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

让代码有更好的兼容性

安装babel插件

npm i -D @babel/core @babel/preset-env @babel-loader core-js

package.json中查看是否成功安装成功。

修改webpack.config.js文件

 //指定webpack打包时要使用的模块module: {//指定要加载的规则rules: [{//test:规则生效的文件//用ts-loader处理ts结尾的文件test: /\.ts$/,use: [{loader: 'babel-loader',  //指定加载器//配置babeloptions: {//设置预定义的环境presets: [//指定环境插件"@babel/preset-env",//配置信息{//要兼容的目标浏览器targets: {"chrome": "88"},//指定corejs的版本"corejs": "3",//使用corejs方式使用usage表示按需加载"useBuiltIns": "usage"}]}},'ts-loader'],  //要使用的loaderexclude: /node-modules/  //要排除的文件}]},

六、面向对象

程序之中所有操作都要通过对象来完成。

操作浏览器要使用window对象,操作网页使用document对象,操作控制台使用console对象。

对象包含属性方法

1. 类class

类是对象的模型,我们通过类创建对象。比如说Car类可以创建汽车的对象。

定义类:

// 使用class关键字定义类
class Person {name: string = 'ruru' //实例属性age: number = 18static sex:string = "女"readonly anim:string = "shushu"  //只读sayHello(){   //定义方法console.log('hello!!')}}
//使用类创建一个对象
const p1 = new Person();

直接定义的属性是实例属性,通过实例访问。

在类中属性前使用static关键字可以定义类属性(静态属性),可以通过类访问

readonly开头的属性只读,不可更改。

方法和类在上述三点是相通的

2. 构造函数和this

class Dog {name: stringage:number// 构造函数在对象创建时调用//再实例方法中,this表示的是当前的实例constructor(name: string, age: number) {this.name = namethis.age = ageconsole.log(this)}
}const d1 = new Dog('wang', 1);
const d2 = new Dog('bai', 2)

这样就可以传入不同参数获得不同的对象

通过this表示当前调用方法的对象。

3. 继承

Dog类

class Dog {name: stringage:numberconstructor(name: string, age: number) {this.name = namethis.age = age}sayHello(){console.log('汪汪汪!')}
}const d1 = new Dog('xiaohei', 2)
d1.sayHello()

Cat类

class Cat {name: stringage: numberconstructor(name: string, age: number) {this.name = namethis.age = age}sayHello() {console.log('喵喵喵~')}}const c1 = new Cat('xiaobai', 1)
c1.sayHello()

这两个类的结构很相似,代码很冗余。

代码提取出来,然后共享

定义一个Animal

class Animal {name: stringage: numberconstructor(name: string, age: number) {this.name = namethis.age = age}sayHello() {console.log('喵喵喵~')}
}class Dog extends Animal {  //继承run(){console.log('旺财在跑')}
}class Cat extends Animal {  //继承sayHello(){console.log('喵喵喵')   //覆盖掉父类的方法,这种叫做方法的重写}
}

使用继承后,子类将拥有父类所有的方法和属性。

通过继承可以将多个类中共有的代码写在一个父类中,避免代码的重复。

可以直接在子类中添加你想要添加属性和方法,可以正常使用,参考Dog里的run方法。

继承中的super,表示当前类的父类

class Dog extends Animal {sayHello() {super.sayHello();}
}

注意:如果在子类写了构造函数,此时在子类的构造函数中必须对父类的构造函数进行构造。

4. 抽象类

禁止一个类来创建对象

abstract开头的类是抽象类,不能创建对象只能作为父类用来继承,没有其它作用。

抽象类中可以添加抽象方法,使用abstract开头,只能定义在抽象类中,子类必须对抽象方法进行重写

abstract class Animal{name:stringconstructor(name:string){this.name = name}abstract sayHello(){  //在子类中必须被重写哦//console.log('动物在叫!')}
}

5. 接口

接口用于定义一个类结构,interface开头

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

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

接口可以在定义类的时候去限制类的结构,接口中的属性都不能有实际值,只定义对象的结构不考虑实际值,接口中的方法都是抽象方法。

定义类时,可以使类去实现一个接口,实现接口就是使类满足接口的要求。

interface myInterface {name: stringage: number
}
const obj: myInterface = {name: 'ruru',age: 18
}

6. 属性的封装

现在属性是在对象中设置的,属性可以任意的被修改。

class Per {name: stringage: numberconstructor(name: string, age: number) {this.name = namethis.age = age}
}
const p2 = new Per('ruru', 20);

数据可随意修改,非常不安全,很危险。

TS 可以在属性前添加属性的修饰符:publicprivate

class Per {_name: string   //改成私有属性,外部不能访问_age: numberconstructor(name: string, age: number) {this._name = namethis._age = age}
}

记得在tsconfig.json文件中配置"noEmitOnError":true

通过在类中添加方法,让外部能间接的获取设置这些属性值。

getName(){return this._name
}
p2.getName()
setName(value:string){this._name = value
}p2.setName('猪')

现在选择主动权在我,我可以控制数据是否能被访问,从而有效保证数据的安全。

getter方法用来读取属性

setter方法用来设置属性

​ - 它们被称为属性的存取器

使用存取器设置name属性:

get name(){	return this._name
}
set name(value){this.name = value
}
p2.name = "猪"  //直接修改即可

私有属性private无法在子类中访问

保护属性protect只能在当前类和子类中访问

7. 泛型

定义函数或者类时类型不明确,执行时才能确定类型

泛型可同时指定多个

function fn<T>(a:T):T{return a;	
}
//指定两个泛型
function fn2<T,K>(a:T,b:K):T{return a+b;
}

使用:

//直接调用
fn(10);//指定泛型
fn<string>("hello")

T extends Inter表示泛型T必须是Inter实现类(子类)

interface Inter{length:number
}
function f3<T extends Inter>(a:T):number{return a.length;
}

对象:

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

总结

love and peace
希望大家学的开心
欢迎指正
在这里插入图片描述


http://www.ppmy.cn/news/1455632.html

相关文章

核心代码分析

核心代码分析 下面的代码主要有两个作用 判断是否为扫描器或者密码爆破工具&#xff0c;进行交互握手&#xff0c;效果是扫描器直接爆3306弱口令。如果是直接连接&#xff0c;去读取设定好的文件&#xff0c;并写入本地保存。 这些函数用于从MySQL数据库中获取指定文件的内容…

LCR 123. 图书整理 I

刷算法题&#xff1a; 第一遍&#xff1a;1.看5分钟&#xff0c;没思路看题解 2.通过题解改进自己的解法&#xff0c;并且要写每行的注释以及自己的思路。 3.思考自己做到了题解的哪一步&#xff0c;下次怎么才能做对(总结方法) 4.整理到自己的自媒体平台。 5.再刷重复的类…

数据结构链表

数据结构链表 链表 1&#xff09;链表的概念及结构: 链表是一种物理存储结构上非连续存储结构&#xff0c;数据元素的逻辑顺序是通过链表中的引用链接次序实现的。 2&#xff09;实际中链表的结构非常多样&#xff0c;以下情况组合起来就有8种链表结构&#xff1a; 单向、双向…

Stable Diffusion学习记录

文章目录 前言电脑配置推荐环境搭建下载地址安装步骤步骤一&#xff0c;打开下载的秋叶整合包&#xff0c;路径秋叶整合包/sd-wenui-aki步骤二&#xff0c;打开下载好的sd-webui-aki-v4.8.7解压包 Stable Diffusion软件配置&#xff0c;插件安装&#xff0c;模型下载Stable Dif…

未授权访问

未授权访问是系统对用户限制不全&#xff0c;或者无限制&#xff0c;可以让任意用户或者限制访问用户&#xff0c;访问到需要权限认证的地址。未授权访问通常是会泄露用户信息&#xff0c;系统信息。某些服务和系统中&#xff0c;未授权访问还可以执行系统命令&#xff0c;操作…

OPENAI中Assistants API的实现原理及示例代码python实现

OPENAI中Assistants API的实现原理及示例代码 前言 OPENAI是一家人工智能公司&#xff0c;致力于研究和开发人工智能技术。其中&#xff0c;Assistants API是OPENAI推出的一项人工智能服务&#xff0c;可以帮助开发者快速构建智能助手。本文将介绍Assistants API的实现原理&a…

Retrofit库中,Call​;Retrofit使用举例;@GET,@PUT区别;

目录 在Retrofit库中,Call​ Retrofit使用举例 Call> listRepos(@Path("user") String user); Call是什么:

CVPR2024论文整理及最新算法整理

CVPR 2024 | 腾讯优图实验室20篇论文入选&#xff0c;含图文多模态大模型、高分辨视觉分割、跨模态生成、人脸识别等研究方向-腾讯云开发者社区-腾讯云 (tencent.com) CVPR2024满分论文出炉&#xff01;分割万物再次火爆AI界-CSDN博客 【综述】三维点云深度学习算法综述,sota…