TypeScript入门基础
Posted 前端More
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了TypeScript入门基础相关的知识,希望对你有一定的参考价值。
文章目录
1 TypeScript介绍
1.1 什么是TypeScript?
TypeScript
简称TS,它是以javascript为基础构建的语言,是JavaScript的超集
(TS是JS的升级版),本质上向这个语言添加了可选的静态类型和基于类的面向对象编程。 TS的目的是为了更安全高效的类型提示和检查
1.2 为什么需要 TypeScript
JavaScript是弱类型语言,很多错误只有在运行时才会被发现,而TypeScript提供了一套静态检测机制,可以帮助我们在编译时就发现错误 。
1.3 JS与TS的相关知识
JS
是一门标准的弱类型且动态类型的语言,所以JS灵活多变,缺失类型系统的可靠性。
TS
是一门标准的强类型且静态类型的语言。
强类型VS弱类型
强类型
:在语言层面就限制了函数的实参类型必须与形参类型相同
弱类型
:语言层面不会限制实参的类型; 我们定义一个变量,不需要考虑它的类型
形参
相当于函数中定义的变量,实参
是在运行时的函数调用时传入的参数。
强类型语言的特点就是不允许程序在发生错误后继续执行
弱类型的一个特点就是在计算时,不同类型之间对使用者透明地对变量进行隐式转换。
相较于弱类型语言,强类型有着明显的优势
:
- 错误更早暴露(编码阶段就能发现并避免类型异常);
- 代码更智能,编码更准确(编辑器时时刻刻都知道变量的类型,作出提示);
- 重构更牢靠(重构时,能及时暴露出相关代码异常信息,可及时准确的对耦合代码进行修改);
- 减少不必要的类型判断(在编码阶段,参数类型已经确定,就不用再对类型做约定判断);
静态类型VS动态类型
静态类型语言
:一个变量在声明时它的类型就是明确的,声明过后,它的类型就不可修改;
动态类型语言
:在代码运行阶段才能明确变量的类型,而且变量的类型随时可以改变;
两者区别
:是否允许随时修改变量的类型 ,
如何区分
:一门语言在编译时报错,那么是静态类型,如果在运行时报错,那么是动态类型。
静态类型的好处
:有利于代码的重构,可以在编译器编译时捕获错误。这样我们在编写代码的时候就能避免很多错误,提高编码的效率!
静态类型语言 | 动态类型语言 |
---|---|
对类型极度严格 | 对类型非常宽松 |
立即发现错误 | 不能立即发现(单元测试) |
运行时性能好 | 运行时性能差 |
自文档化 | 可读性差(工具生成文档) |
1.4 TypeScript特性
- 支持最新的JavaScript新特性(ES6-ES12),添加ES不具备的新特性
- 支持代码静态检查,拥有了更加严格的语法和更强大的功能 ,TS可以在代码执行前就完成代码的检查,
减小了运行时异常的出现的几率; - 同样的功能,TS的代码量要大于JS,但由于TS的代码结构更加清晰,变量类型更加明确,在后期代码的维护中TS却远远胜于JS;
- 支持诸如C,C++,Java,Go等后端语言中的特性 (枚举、泛型、类型转换、命名空间、声明文件、类、接口等) ,有强大的开发工具以及丰富的配置选项。
1.5 TypeScript安装
安装Node
:https://nodejs.org/zh-cn/
安装ts
:
npm i -g typescript
将ts文件编译为js文件(生成一个和ts文件名称相同的js文件),然后执行js文件
//编译ts文件
tsc XXX.ts
//运行js文件
node XXX.js
也可以安装ts-node直接运行ts文件 ,不需要编译为js
/安装ts-node
npm i -g ts-node
//直接运行ts文件
ts-node XXX.ts
2 TypeScript的基本类型
2.1 类型声明
类型声明
给变量设置了类型,使得变量只能存储某种类型的值。
通过类型声明可以指定TS中变量(参数字、形参)的类型,指定类型后,当为变量赋值时,TS编译器会自动检查值是否符合类型声明,符合则赋值,否则报错。
语法如下:
// 声明一个变量
let 变量: 类型;
// 声明一个变量并给其赋值
let 变量: 类型 = 值;
// 声明一个函数
function fn(参数: 类型, 参数: 类型): 函数返回值类型
...
// a 的类型设置为了number,在以后的使用过程中a的值只能是数字
let a: number;
a = 10;
a = 33;
a = 'hello'; // 此行代码会报错,因为变量a的类型是number,不能赋值字符串
自动类型判断
:TS拥有自动的类型判断机制,当对变量的声明和赋值是同时进行的,TS编译器会自动判断变量的类型,所以变量的声明和赋值时同时进行可以省略掉类型声明。
注
:虽然可以省略类型,但声明类型对定义函数有极大的提升
let a = 1;
a = 'sj';//报错 不能将类型'string'分配给类型'number'
2.2 类型分类
类型 | 例子 | 描述 |
---|---|---|
number | 1, -33, 2.5 | 任意数字 |
string | ‘hi’, “hi”,模板字符串`` | 任意字符串 |
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 | enumA, B | 枚举,TS中新增类型 |
2.2.1 number
number
:任意
let a: number;
// a 的类型设置为了number,在以后的使用过程中a的值只能是数字
a = 10;
a = 33;
// a = 'hello'; // 此行代码会报错,因为变量a的类型是number,不能赋值字符串
2.2.2 string
string
:任意字符串
let color: string = "blue";
color = 'red';
2.2.3 boolean
boolean
:布尔值true或false
let isDone: boolean = false;
2.2.4 字面量
字面量
:字面量不仅可以表示值,还可以表示类型,即所谓的字面量类型。也可以使用字面量去指定变量的类型,通过字面量可以确定变量的取值范围。
let a: 10; //a的值只能为10
//可以使用|来连接多个类型(|为联合类型表示取值可以为多种类型中的一种)
let b: 'male' | 'female'; //b的值只能二选一
b = 'male';
b = 'female';
let c: boolean | string;
c = true;
c = 'sd ';
2.2.5 any
any
:任意类型
一个变量设置为any后相当于对该变量关闭了TS的类型检测,故不建议使用。声明变量如果不指定类型,则TS解析器会自动判断变量的类型为any(隐式的any)。
let d: any = 4;
d = 'hello';
let e ;
e=1;
e=true;
//d的值为any,它可以赋值给任意变量
let s:string
s=d;//这样变量s的类型检测也关闭了
2.2.6 unknown
unknown
:类型安全的any,不能直接赋值给其他变量
let e: unknown;
e="hello"
let f:string
f=e;//报错 类型unkonwn不能赋值给string类型
2.2.7 void
void
:void表示没有任何类型,和其他类型是平等关系,不能直接赋值:
声明一个void类型的变量没有什么大用,我们一般也只有在函数没有返回值时去声明。
//void用来表示空
function fn(): void
return undefined//除了undefined的其他类型的返回值会报错
2.2.8 never
never
:不能是任何值
//never 表示永远不会返回结果 连undefined都不能返回,一般用来报错
function fn1(): never
throw new Error('报错了');
2.2.9 object
object
:任意的JS对象
//1.定义对象结构的类型声明
/*
语法:属性名:属性值,属性名:属性值
在属性名后边加上?,表示属性是可选的
*/
let b: name: string; age?: number ;
b = name: '孙悟空', age: 18 ;
//[xxx:string]:any 表示任意类型的属性
let c: name: string; [propName: string]: any ;
c = name: '猪八戒', age: 18, gender: '男' ;
//2.定义函数结构的类型声明
//我们一般会限制函数有几个参数,参数的类型,返回值的类型,可以以一种类似箭头函数的方式来声明一个函数类型的变量
/*
语法:(形参:类型,形参:类型...) => 返回值
*/
let d: (a: number, b: number) => number;
d = function (n1, n2): number
return n1 + n2;
;
2.2.10 array
array
:任意JS数组
/*
语法:类型[]或Array<类型>
*/
//如string[]表示字符串数组 (在元素类型后面接上[]) Array<number>表示数字数组
let e: string[]
//or
let e: Array<string>;
2.2.11 tuple
tuple
: 元组,TS新增类型,就是固定长度(数量)数组
元组中包含的元素,必须与声明的类型一致,数量要对应,且顺序也要一一对应
/*
语法:[类型,类型,类型]
*/
let h: [string,string,number];//里面两个字符串类型,一个数字
h = ['s', 'f',1];//必须对应两个字符串,一个数字,顺序也不能变化
2.2.12 enum
比如我们在定义一个对象的时候 let person = name: ‘zs’, gender: ‘male’ 。像gender
这种属性的取值一般只有两个,所以在存储的时候用数字来代替,可以提高效率,可以定义0
表示女性,1
表示男性
enum
:枚举,TS中新增类型,把所有可能的情况全部列出来,适合用于多个值进行选择的场景,
//enum:结果是多个值进行选择
enum Sex
Male,
Female,
let i: name: string; sex: Sex ;
i =
name: '张三',
sex: Sex.Male,
;
console.log(i.sex === Sex.Male);//true
2.2.13 联合类型
联合类型
:表示取值可以为多种类型中的一种,使用 |
分隔每个类型。
let h: string | number;
h = '张三';
h = 18;
2.2.14 交叉类型
交叉类型
:是将多个类型合并为一个类,使用&
,表示同时,求并集
let j: name: string & age: number ;
j = name: '张三', age: 18 ;
交叉类型主要作用是将多个接口类型合并成一个类型,从而实现等同接口继承的效果,也就是所谓的合并接口类型
2.2.15 类型别名type
类型别名(type)
:用来给一个类型起个新名字。 仅仅是给类型取了一个新的名字,并不是创建了一个新的类型,类型别名常用于联合类型
type Message = string | string[];
let greet = (message: Message) =>
// ...
;
2.2.16 类型断言
类型断言
:有些情况下,变量的类型对于我们来说是很明确,但TS编译器并不清楚,可以通过类型断言来告诉编译器变量的类型,断言有两种形式:
//类型断言,可以用来告诉编译器变量的实际类型
/*
语法: (变量 as 类型) 或 < 类型 > 变量
*/
let e: unknown;
e='ss' //e实际是字符串,但e的类型设置的是unkonwn
let f: string;
f=e//报错
f = e as string;//告诉ts编译器e就是字符串,这样就不会出现上述f=e报错的情况
// 或
f = <string>e;
3 编译选项
3.1 自动编译文件
编译文件时,使用 -w 指令后,TS编译器会自动监视文件的变化,并在文件发生变化时对文件进行重新编译。
tsc xxx.ts -w
3.2 自动编译整个项目
一个文件一个文件的编译太麻烦了,我们可以对整个项目进行编译
首先在项目根目录下创建一个ts的配置文件 tsconfig.json
,然后就可以使用tsc
指令,编译项目下的所有ts文件为js文件,当然也可以开启监视模式tsc -w
监视所有的文件
3.3 tsconfig.json的配置选项
tsconfig.json配置总览
"compilerOptions":
"target": "es5", // 指定 ECMAScript 目标版本: 'ES5'
"module": "commonjs", // 指定使用模块: 'commonjs', 'amd', 'system', 'umd' or 'es2015'
"moduleResolution": "node", // 选择模块解析策略
"experimentalDecorators": true, // 启用实验性的ES装饰器
"allowSyntheticDefaultImports": true, // 允许从没有设置默认导出的模块中默认导入。
"sourceMap": true, // 把 ts 文件编译成 js 文件的时候,同时生成对应的 map 文件
"strict": true, // 启用所有严格类型检查选项
"noImplicitAny": true, // 在表达式和声明上有隐含的 any类型时报错
"alwaysStrict": true, // 以严格模式检查模块,并在每个文件里加入 'use strict'
"declaration": true, // 生成相应的.d.ts文件
"removeComments": true, // 删除编译后的所有的注释
"noImplicitReturns": true, // 不是函数的所有返回路径都有返回值时报错
"importHelpers": true, // 从 tslib 导入辅助工具函数
"lib": ["es6", "dom"], // 指定要包含在编译中的库文件
"typeRoots": ["node_modules/@types"],
"outDir": "./dist",
"rootDir": "./src"
,
"include": [
"./src/**/*.ts"
],
"exclude": [
"node_modules",
"dist",
"**/*.test.ts",
]
3.3.1 include
- 指定需要编译的ts文件目录,是一个数组,其中
*
表示任意文件**
表示任意目录 - 默认值:
["**/*"]
"include":["src/**/*", "test/**/*"] // 所有src目录和test目录下的文件都会被编译
3.3.2 exclude
- 指定不需要被编译的文件目录
- 默认值:
["node_modules", "bower_components", "jspm_packages"]
"exclude": ["./src/hello/**/*"] // src下hello目录下的文件都不会被编译
3.3.3 extends
-
定义被继承的配置文件(和引入外部文件类似)
"extends": "./configs/base" // 自动包含configs目录下base.json中的所有配置信息
3.3.4 files
-
指定被编译文件的列表,只有需要编译的文件少时才会用到(和include类似)
-
列表中的文件都会被TS编译器所编译
"files": [ "core.ts", "sys.ts", "types.ts", "scanner.ts", "parser.ts", "utilities.ts", "binder.ts", "checker.ts", "tsc.ts" ]
3.3.5 compilerOptions
重要的编译选项,在compilerOptions中包含多个子选项,用来完成对编译的配置
target
:设置ts代码编译的目标版本
对于选项有哪些可选值,我们可以随便写一个值,编辑器会提示我们有哪些可选值
"compilerOptions":
//可选值: “ES3”(默认), “ES5”, “ES6”, “ES2015”, “ES2016”, “ES2017”, “ES2018”, “ES2019”, “ES2020”, “ES2021”, “ESNext”.
"target": "ES6"//ts代码将会被编译为ES6版本的js代码
lib
:指定代码运行时所包含的库(宿主环境),一般运行在浏览器环境下的,就不需要自己单独设置这个
"compilerOptions":
//可选值:“ES5”, “ES6”, “ES2015”...很多
"lib": ["ES6", "DOM"]
module
:设置编译后代码使用的模块化系统
"compilerOptions":
//可选值:“CommonJS”, “AMD”, “System”, “UMD”, “ES6”, “ES2015”, “ES2020”, “ESNext”, “None”, “es2022”, “node12”, “nodenext”
"module": "CommonJS"
outDir
:指定编译后文件的所在目录
"compilerOptions":
"outDir": "./dist"//编译过的js文件将会生成到dist目录。可以将源码与编译后的代码分开存放
outFile
:将所有的文件编译为一个js文件
- 默认会将所有的编写在全局作用域中的代码合并为一个js文件,如果 module 制定了 None、System 或 AMD 则会将模块一起合并到文件之中,这种合并由打包工具去做。
"compilerOptions":
"outFile": "./dist/app.js"
rootDir
:指定代码的根目录,默认情况下编译后文件的目录结构会以最长的公共目录为根目录,通过rootDir可以手动指定根目录
"compilerOptions":
"rootDir": "./src"
3.3.6 其他配置
//是否对js文件编译,默认值:false
"allowJs":false,
//是否对js文件进行语法检查,默认值:false
"checkJs":false
//是否删除注释,默认值:false
"removeComments":false
//不生成编译后的文件,默认值:false
"noEmit":false
//当有错误的时候不生成编译后的文件,默认值:false
"noEmitOnError":false
//是否生成sourceMap,默认值:false
"remove":false
3.3.7 严格检查
//是否启用所有的严格检查(总开关),设置true后相当于开启了所有的严格检查,后面的检查不需要在写了,默认值:false
"strict":false
//是否总是以严格模式对代码进行编译,默认值:false
"alwaysStrict":false
//是否允许隐式的 any 类型,默认值:false
"noImplicitAny":false
//是否允许隐式的 this,默认值:false
"noImplicitThis":false
//严格检查bind、call和apply的参数列表,默认值:false
"strictBindCallApply":false
//严格检查函数的类型,默认值:false
"strictFunctionTypes":false
//检查是否存在空值,默认值:false 可以用a?.b判断a是否是空值
"strictNullChecks":false
//严格检查属性是否初始化,默认值:false
"strictPropertyInitialization":false
3.3.8 额外检查
//是否检查switch语句包含正确的break
"noFallthroughCasesInSwitch":false
//是否检查函数没有隐式的返回值
"noImplicitReturns":false
//是否检查未使用的局部变量
"noUnusedLocals":false
//是否检查未使用的参数
"noUnusedParameters":false
//检查不可达代码;true:忽略不可达代码,false:不可达代码将引起错误
"allowUnreachableCode":false
4 使用Webpack打包TS代码
通常情况下,实际开发中我们都需要使用构建工具对代码进行打包;TS同样也可以结合构建工具一起使用,下边以webpack为例
介绍一下如何结合构建工具使用TS;
4.1 初始化项目
通过执行命令 npm init -y
初始化一个项目并创建package.json文件
使用tsc --init
创建ts的配置文件tsconfig.json
创建src/index.ts
文件,用来编写ts代码
4.2 安装依赖
安装以下依赖包
npm i -D webpack webpack-cli webpack-dev-server typescript ts-loader clean-webpack-plugin
-
webpack:构建工具webpack
-
webpack-cli:webpack的命令行工具
-
webpack-dev-server:webpack的开发服务器
-
typescript:ts编译器
-
ts-loader:ts加载器,用于在webpack中编译ts文件
-
html-webpack-plugin:webpack中html插件,用来自动创建html文件
-
clean-wepack-plugin:webpack中的清除插件,每次构建都会先清除目录
4.3 配置webpack
根目录下创建webpack的配置文件webpack.config.js
:
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const CleanWebpackPlugin = require("clean-webpack-plugin");
module.exports =
// 指定入口文件
entry: "./src/index.ts",
// 开发模式使用,方便查错误
devtool: "inline-source-map",
// 配置服务器
devServer:
contentBase: "./dist",
,
// 指定打包文件所在目录
output:
path: path.resolve(__dirname, "dist"),
//打包后的文件
filename: "bundle.js",
environment:
arrowFunction: false, // 关闭webpack的箭头函数,可选
,
,
// 用来设置引用模块
resolve:
extensions: [".ts", ".js"],//以ts js结尾的文件都可以作为模块使用
,
// 配置webpack的loader(打包使用的模块)
module:
//加载规则
rules: [
//规则生效的文件
test: /.ts$/,//以ts结尾的文件
//要使用的loader
use:
loader: "ts-loader",
,
//排除的文件
exclude: /node_modules/,
,
],
,
// 配置webpack的插件
plugins: [
// 构建前清除目录
new CleanWebpackPlugin(),
//自动创建html文件
new HtmlWebpackPlugin(
template: "./src/index.html",
软件开发入门教程网之TypeScript 基础语法