(持续更新中)干货! 快速上手typescript的学习笔记 (对比JS特性,环境搭建,webpack配置,ts编译配置)
前提需要有js的基础
文章目录
TypeScript
产生背景
TypeScript 起源于使用JavaScript开发的大型项目 。由于JavaScript语言本身的局限性,难以胜任和维护大型项目开发。因此微软开发了TypeScript ,使得其能够胜任开发大型项目。
什么是TypeScript?
- 以JavaScript为基础构建的语言
- 一个JavaScript的超集
- 可以在任何支持JavaScript的平台中执行
- TypeScript扩展了JavaScript并添加了类型
- TS不能被JS解析器直接执行 TS—编译—>JS
TypeScript增加了什么
- 类型:抽象、枚举等
- 支持ES的新特性
- 添加ES不具备的新特性
- 丰富的配置选项:比如TS可以被配置为编译成任何版本的JS
- 强大的开发工具
TypeScript开发环境搭建
-
安装node.js
-
使用npm全局安装typescript
-
进入命令行
-
输入:npm i -g typescript
-
- 查看是否安装成功
-
创建一个ts文件
-
使用tsc对ts文件进行编译
-
自动生成JS文件
基本类型
-
类型声明
-
如果类型声明和赋值分开
let/const/var 变量名 : 类型
-
如果声明和赋值一起写,会自动进行类型检测
-
-
类型
类型 例子 描述 number 1,-33,20 任意数字 string ‘hello’, “hello” 任意字符串 boolean true,false 布尔值true或false 字面量 其本身 限制变量的值就是该字面量的值 any * 任意类型 unknown * 类型安全的any void 空值(undefined) 没有值(或undefined) nerver 没有值 不能是任何值 object {name: ‘abc’} 任意的JS对象 array [1,12,3] 任意JS数组 tuple [4,5] 元组,TS新增类型,固定长度数组 enum enum{A,B} 枚举,TS中新增类型 -
字面量
let a: 10; a = 10; let b: "male" | "female"; // 赋值为"male" |或"female" b = "male"; b = "female"; b = "hello" // 报错 ERROR!
-
any
表示是任意类型,一个变量设置类型为any后相当于对该变量关闭了TS的类型检测
let a = any; // 显式声明any let a; //隐式声明any // 赋值 a = 10; // 正常 a = 'hello'; // 正常 a = true; // 正常
-
unknown
类型安全的any,不能直接给其他类型的变量
let e: unknown; e = 10; e = 'hello'; e = true;
看似和any一样,其实不然。
any举例:
let s:string; let d; // any s = d; // 不报错
unknown举例:
let e: unknown; let s: string; s = e; // 报错 // 如果非要赋值 // if语句 if(typeof e === 'string') { s = e; } // 类型断言,告诉编译器e是字符串 s = e as string; // 另外一种写法 s = <string>e;
-
void
主要作为返回值,用来表示空,以函数为例,就表示没有返回值的函数。
function fn(): void { // ... }
-
never
表示永远不会返回结果
function fn2(): never{ // ... } // 有一些函数永远不会返回结果 function showError(): never{ throw new Error('报错了!'); }
-
object
object表示一个js对象
// 一般不使用这种声明 let a: object; a = {}; a = function () { } // 一般使用下面的写法,要求格式和类型 let b: {name: string}; b = {name: '孙悟空'} // 在属性名后面加上? 表示属性是可选的 let c: {name: string, age?: number}; c = {name: '孙悟空'}; // 不报错 // 但是不能把需要的所有属性都写一边,所以就用下面的语法 // [propName: string]: any便是任意类型的属性 let d: {name: string, [propName: string]: any}; c = {name: '猪八戒', age: 1, gender: '男'}; // 声明function结构的类型声明 // (形参: 类型, 形参: 类型) => 返回值 let e: (a: number, b: number) => number; d = function(n1: number, n2: number): number { return 10; }
-
array
// 声明1:类型[] let arr1: string[]; arr1 = ['a', 'b', 'c']; // 声明2:Array<类型> let arr2: Array<number>; arr2 = [1, 2, 3];
-
tuple
元组,固定长度的数组
// 简单的声明 let arr3: [string, string]; arr3 = ['a', 'b']; arr3 = ['a', 'b', 'c']; //报错
-
enum
枚举,把所有可能的类型列出来
enum Gender{ Male = 0; Female = 1; } let i: {name: string, gender: Gender}; i = { name: '孙悟空', gender: Gender.Male; // 0 } console.log(i.gender === Gender.Male);
-
| 和 &
let a: number | string let b: {name: string} & {age: number}; b = {name: '孙悟空', age: 18};
-
类型的别名
// 引例: let k: 1 | 2 | 3 | 4; let l: 1 | 2 | 3 | 4; // 麻烦 // 解决 type myType = 1 | 2 | 3 | 4; let k: myType; let j: myType;
-
编译文件配置
我们写一行代码手动敲tsc命令编译一次是很耗时的,相当麻烦,也无法自动编译,而且无法编译所有的ts文件。
所以目录下增加tsconfig.json
配置文件用来编译所有的ts文件。
这时就算没有写内容,打开这个目录,执行tsc,它会自动编译这个目录下所有的ts文件成js文件,下面介绍各配置项
tsconfig.json常用的各配置项
以下列出常用的tsconfig.json
配置
{
/*
tsconfig.json ts编译器的配置文件
*/
/*
"include" 用来指定哪些ts文件需要被编译
-> 路径: ** 表示任意目录 * 表示任意文件
*/
"include": [
"./src/**/*"
],
/*
"exclude" 用来指定哪些ts文件不希望被编译,比如node_module下的ts文件
默认值: ["node_modules", "bower_components", "jspm_packages"]
*/
"exclude": [
"./src/abc/*"
],
/*
"extends" 定义被继承的配置文件
下面会让此配置文件中自动包含config下base.json中的所有配置信息
*/
"extends": "./config/base",
/*
"files" 指定被编译文件的列表,只有需要编译的文件少时才会用到
列表中的文件都会被TS编译器所编译
*/
"files": [
"core.ts",
"sys.ts"
],
/*
"compilerOptions" 编译选项时配置文件中非常重要也比较复杂的配置选型
在compilerOptions中包含多个子选项,用来完成对编译的配置
*/
"compilerOptions": {
// target
// 设置ts代码编译成JS的目标版本
// 可选值:ES3(默认),ES5,ES6/ES2015,ES7/ES2016,ES2017,ES2018,ES2019,ES2020,ES2021
"target": "ES2015",
// lib
// 指定代码运行时所包含的库(宿主环境) 一般情况下不改动
// 可选值:ES5,ES6/ES2015,ES7/ES2016,ES2017,ES2018,ES2019,ES2020,ESNext,DOM...
"lib": ["ES2015", "DOM"],
// module
// 设置编译后代码使用的模块化系统,指定模块化的规范
// 可选值:CommonJS,AMD,UMD,ES2020.ESNext,None,System
"module": "CommonJS",
// outDir
// 用来指定编译后js文件所在的目录
"outDir": "./distJS",
// outFile
// 将代码合并为一个文件,全局作用域中的代码会合并
// 如果要合并几个模块,要用AMD或者System
"outFile": "./distJS/app.js",
// allowJs
// 是否对js文件进行搬移,默认是false
"allowJs": false,
// checkJs
// 是否检查js代码是否符合语法规范,默认是false
"checkJs": false,
// strict 建议开启
// 所有严格检查的开关 默认false
"strict": false,
// removeComments
// 是否移除注释,默认false
"removeComments": false,
// noEmit
// 不生成编译后的js文件
"noEmit": false,
// noEmitOnError
// 当有错误时,它不会生成编译后的js文件,默认false
"noEmitOnError": true,
// alwaysStrict
// 用来设置编译后的文件是否使用严格模式,默认false
"alwaysStrict": false,
// noImplicitAny
// 检查隐式any,true为不允许隐式any 默认false
"noImplicitAny": true,
// noImplicitThis
// 检查隐式this,来源不明确的this 默认false
"noImplicitThis": true,
// strictNullChecks
// 严格的检查空值null隐患 默认值false
"strictNullChecks": false
}
}
使用webpack打包ts代码
安装webpack
npm i -D webpack webpack-cli typescript ts-loader
配置webpack
只讲ts有关的,打包css,js图片等loader配置可以看我另外一个文章
webpack.config.js
// 引入一个包
const path = require('path');
// webpack中的所有配置信息都应该写在module.exports中
module.exports = {
// 指定入口文件
entry: "./src/index.ts",
// 指定打包文件所在的目录
output: {
// 指定打包文件的目录
path: path.resolve(__dirname,'dist'),
// 打包后文件的名字
filename: "bundle.js"
},
// 指定wegpack打包时要使用的模块
module: {
// 指定要加载的规则
rules: [
{
// test指定的时规则生效的文件
test: /\.ts$/,
// 要使用的loader
use: 'ts-loader',
// 要排除的文件
exclude: /node_modules/
}
]
}
}
配置ts编译规则
tsconfig.json
{
"compilerOptions": {
"module": "ES2015",
"target": "ES2015",
"strict": true
}
}
增加package.json中script的命令
"build": "webpack"
这样最基本的配置已经完成了
试编译ts代码
编写index.ts
function sum(a: number, b: number): number{
return a + b;
}
console.log(sum(1, 10));
npm run build
报的错是没指定环境是生产模式还是开发模式
想要解决这个错误就在webpack配置文件里增加mode配置,指定模式即可。
安装html-webpack-plugin
npm i -D html-webpack-plugin
让webpack自动生成html
配置插件
// 引入一个包
const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path');
// webpack中的所有配置信息都应该写在module.exports中
module.exports = {
// 指定入口文件
entry: "./src/index.ts",
// 指定打包文件所在的目录
output: {
//...
},
// 指定wegpack打包时要使用的模块
module: {
//...
},
"mode":"development",
// 配置webpack插件
plugins: [
new HtmlWebpackPlugin(),
]
}
这样它会在build以后自动生成html并且自动引入ts编译后的js文件
安装webpack-dev-server
npm i -D webpack-dev-server
可以让我们的项目跟浏览器联系在一起,代码一修改后自动刷新,展现在浏览器中
安装完后增加script命令
"strat": "webpack serve --open chrome.exe"
安装 clean-webpack-plugin
npm i -D clean-webpack-plugin
可以在每次新编译后,将dist文件夹里面的文件清空,把新的文件加进去,让dist文件夹里面都是最新编译的文件。
配置webpack,告诉它引用的模块
因为如果你再创建一个ts,在index.ts中引入了新建的ts,webpack并不知道新建的ts可以作为模块引入,它会报错。
增加webpack配置
// 用来设置引入模块
resolve: {
extensions: ['.js', '.ts']
}
安装babel.js以提高兼容性
因为现在编译出来的js为ES6的语法,对于像IE的兼容性很不好,所以现在引入babel.js将我们的语法编译成像ES5提高兼容性。
安装
npm i -D @babel/core @babel/preset-env babel-loader core-js
preset-env 是babel预置不同的环境使得兼容不同的浏览器
core-js 模拟js运行环境,可以让老浏览器很好的运行js
配置webpack
// 引入一个包
const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path');
const { CleanPlugin } = require('webpack');
// webpack中的所有配置信息都应该写在module.exports中
module.exports = {
// 指定入口文件
entry: "./src/index.ts",
// 指定打包文件所在的目录
output: {
// 指定打包文件的目录
path: path.resolve(__dirname,'dist'),
// 打包后文件的名字
filename: "bundle.js"
},
// 指定wegpack打包时要使用的模块
module: {
// 指定要加载的规则
rules: [
{
// test指定的时规则生效的文件
test: /\.ts$/,
// 要使用的loader
use: [
// 配置babel
{
// 指定加载器
loader: "babel-loader",
// 设置babel
options: {
// 设置预定义的环境
presets: [
[
// 指定环境的插件
"@babel/preset-env",
// 配置信息
{
targets: {
// 指定兼容浏览器的版本
"chrome": "58",
"ie": "11",
},
// 指定corejs的版本
"corejs":"3",
// 使用corejs的方式"usage表示按需加载
"useBuiltIns":"usage"
}
]
]
}
},
'ts-loader'
],
// 要排除的文件
exclude: /node_modules/
}
]
},
"mode":"development",
// 配置webpack插件
plugins: [
new HtmlWebpackPlugin({
//title:"这是一个自定义的title"
template: "./src/index.html"
}),
new CleanPlugin()
],
// 用来设置引入模块
resolve: {
extensions: ['.js', '.ts']
}
}
index.ts:
const abc = {name:'abc', age: 12};
console.log(abc);
不使用babel进行编译,他编译后的变量声明是const
使用babel进行编译,编译后变成了var声明变量
像ie11没有Promise,如果我们使用了Promise,corejs会产生效果,使用自己实现的promise加在编译后的js中
index.ts
const abc = {name:'abc', age: 12};
console.log(abc);
console.log(Promise);
进行编译,corejs会加入很多自己实现的东西
但是这样在ie中还是会出错,因为webpack使用了箭头函数,我们可以增加配置项让webpack不使用箭头函数
output:{
// ...
// 告诉webpack不使用箭头函数
environment: {
arrowFunction: false
}
}
这样ie就不会报错了
面向对象
以下话摘抄与尚硅谷的****
面向对象是程序中一个非常重要的思想,它被很多同学理解成了一个比较难,比较深奥的问题,其实不然。面向对象很简单那,简而言之就是程序之中所有的操作都需要通过对象来完成。
- 举例来说
- 操作浏览器需要用到window对象
- 操作网页要用到document对象
- 操作控制台要用到console对象
一切操作都要通过对象,也就是所谓的面向对象,那么对象到底是什么呢?这就要先说到程序是社么,计算机程序的本质就是对现实事务的抽象,抽象的反义词是具体,比如:照片是一个具体的人的抽象,汽车模型是对具体汽车的抽象等等。程序也是对事务的抽象,在程序中我们可以表示一个人,一条狗,一把枪,一颗子弹等等所有的事物,一个事物到了程序中就变成了一个对象。
在程序中所有的对象都被分成了两个部分,数据和功能,以人为例,人的姓名、性别、年龄、身高等属于数据,人可以说话吃饭睡觉,这些属于人的功能,数据在对象中被称为属性,而功能就被称为方法,所以简而言之,在程序中一切皆是对象。