TypeScript学习笔记
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了TypeScript学习笔记相关的知识,希望对你有一定的参考价值。
一. 环境搭建
- 安装Node.js
- npm i -g typescript
- 创建ts文件
test.ts
,编译:tsc test.ts
二. 基本类型
1. 类型声明
语法:
let 变量:类型;
let 变量:类型=值;
function fn(参数:类型,参数:类型):类型
实例:
let myStr: string = "123";
let myNum: number;
console.log(myStr);
myNum = 100;
console.log(myNum);
输出:
var str = "123";//默认编译为ES3版本的JS代码
var num;
console.log(str);
num = 100;
console.log(num);
如果变量的声明和赋值是同时进行的,TS可以自动对变量进行类型检测。
let c = false;
c = 123;//error
如果不需要写明类型就能自动判断,那么我们前面写明的类型限制会显得很鸡肋,反正写不写都一个样。
但是,我们常需要做的类型限制不仅仅只是变量,或者说对变量的限制需求没有那么高,真正高的是函数:
function sum(a,b)
return a+b;
如果不做类型检测,若传入的是123以及"456",则不会报错,且输出为“123456”。若结果用到别的地方,则会导致一连串的错误。
function sum(a:number,b:number):number
return a+b;
sum("123",456);//类型“string”的参数不能赋给类型“number”的参数。
sum(123,456,789);//应有 2 个参数,但获得 3 个。
let result = sum(1,2);//悬浮result:let result: number
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中新增类型 |
- 可以使用字面量进行类型声明
let a:10;//相当于常量
a = 10;//√
a = 11;//不能将类型“11”分配给类型“10”
也可以使用 | 连接多个类型(联合类型)
let b: "male" | "female";
b = "male";
b = "female";
b = "hello"; //不能将类型“"hllo"”分配给类型“"male" | "female"”。
let c: boolean | string;
c = true;
c = "hello";
- any表示的是任意类型,相当于对该变量关闭了TS的类型检测。
// 显示any
let d:any;
d = 10;
d = "hello";
d = true;
// 隐式any
let dd;
dd = 10;
dd = "hello";
- unknown表示未知类型(也可以赋值任意值,但是是类型安全的any):
let e:unknown;
e = 10;
e = "hello";
区别:
let s:string;
s = d;//d是any,可以赋值给任意类型
s = e; //e是unkonwn,虽然上面赋值了“hello”,但是类型不匹配。
//不能将类型“unknown”分配给类型“string”。
类型断言:告诉解析器的实际类型。
//(告诉编译器,它就是字符串)
s = e as string;
- void:用来表示空,没有返回值的函数。
function fn():void
//return null;
//return undefined;
// no return
- never:表示永远不会返回结果。连undefined都不返回。
function fn2():never
throw new Error(报错了!)
- object:表一个JS对象
let a:object;
a = ;
a = function();//万物皆对象,函数也是对象
可以用来指定对象包含哪些属性,属性名后接?,表示属性是可选的。
let b:name:string,age?:number;
b = name:皮卡丘,age:2;
//但是不能额外新增其他的属性
b = name:孙悟空,skill:七十二变;//error
//不能将类型“ name: string; skill: string; ”分配给类型“ name: string; age?: number; ”。
//对象文字可以只指定已知属性,并且“skill”不在类型“ name: string; age?: number; ”中。
[propName:String]:any
可以表示任意类型的属性。propName
可以是任意的内容。
let b:name:string,[xx:string]:any;
b = name:孙悟空,skills:七十二变;//√
- 函数结构的类型声明:
(形参:类型,形参:类型)=>返回值
let d:(a:number,b:number)=>number;
- 数组声明:
类型[]
,Array<类型>
//字符串数组
let strArr:string[];
strArr = [1,a,c];
// 数字数组
let numArr:Array[number];
numArr = [1,2,50];
TS除了保留原有的JS类型之外,还额外新增了两种类型:tuple,enum
- 元组tuple:固定长度的数组。语法:
[类型,类型,类型]
let h:[string,string];
h = [hello];//error
h = [hello,123];
h = [hello,123];//error
h = [hello,123,456];//error
- 枚举enum:
问题:下面的0和1,别人可能不知道1表示男还是女?
let i:name:string,gender:0|1;
i=
name:孙悟空,
gender:1 //male
使用枚举解决:
enum Gender
Male = 0,
Female = 1
let i:name:string,gender:Gender;
i=
name:皮卡丘,
gender:Gender.Male
console.log(i.gender === Gender.Male);
&表示同时具有:
let j:name:string&age:number
j = name:皮卡丘,age:1;
let nonsene :number & string//毫无意义
type
表示类型别名:遇到特别长的声明可以使用这个。
type myType = 1|2|3|4|5
let j:myType
let k:myType
j = 2;
k = 6;//error
三. 编译选项
总不能每次都是手动通过tsc xxx.ts进行编译成js文件吧?
- 编译器自动监视ts文件
-w
:(watch)监视
tsc test.ts -w
-
tsconfig.json
:ts编译器的配置文件。文档:https://aka.ms/tsconfig.json
初始化:tsc -init
- include:指定编译的文件目录
- exclude:定义需要排除的文件
- extends:定义被继承的配置文件
- files:定义编译的文件列表
- compilerOptions:编译器的选项
- target:指定ts编译的目标版本。(如果不清楚可填的值,可以填一个错误的,看报错信息)
- es3, es5, es6, es2015, es2016, es2017, es2018, es2019, es2020, es2021, es2022, esnext
- module:指定要使用的模块化的规范。
- none, commonjs, amd, system, umd, es6, es2015, es2020, es2022, esnext, node12, nodenext
- lib:用来指定项目中要使用的库
- outDir:指定编译后的文件所处目录。
- "./dist"
- outFile:将代码合并为一个文件。只有amd和system模式(module)支持该模式。不适合模块化。
- allowJs:是否对JS文件进行编译,默认是false
- true | false
- checkJs:是否检查JS代码是否符合语法规范。默认是false。
- true:若修改为true,则会在js文件里面出现语法检查。
- removeComments:是否移除注释
- noEmit:不生成编译后的文件。
- noEmitOnError:当有错误的时候,不生成编译的文件。
- 。。。
四. Webpack + TS
(一)基础配置
1. 配置依赖
cnpm i -D webpack webpack-cli typescript
cnpm i -D html-webpack-plugin ts-loader
cnpm i -D webpack-dev-server
- webpack脚手架:webpack,webpack-cli
- ts-loader:加载TS文件内容
- html-webpack-plugin:生成模板html,自动引入依赖
- webpack-dev-server:即时更新
- TS环境:typescript
2. webpack.config.js
新建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",
// 输出
output:
path:path.resolve(__dirname,dist),
filename:bundle2.js,
clean:true,
,
mode:development,
// 打包使用模块
module:
//指定加载规则
rules:[
test:/\\.ts$/,
use:ts-loader,
//排除文件
exclude:/node-modules/
]
,
plugins:[
// new CleanWebpackPlugin(),
new HTMLWebpackPlugin(
// title:LearningTs,
template:./src/index.html
),
],
// 用来设置引用模块
resolve:
extensions:[.ts,.js]
3. tsconfig.json
创建tsconfig.json文件,用于指定ts编译后的内容
"compilerOptions":
"target": "es2015",
"module": "es2015",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": false,
"skipLibCheck": true
4. 构建指令配置
在package.json中修改script配置,增加build指令以及start指令:
"scripts":
"test": "echo \\"Error: no test specified\\" && exit 1",
"build":"webpack",
"start":"webpack serve"
,
此时,通过npm run build
即可看到最简单的构建产物。
(二)清除旧的打包产物
- 方式一:引入插件
- 安装:
cnpm i -D clean-webpack-plugin
- 引入config
const CleanWebpackPlugin = require(clean-webpack-plugin);
- 注册plugin
plugins:[ new CleanWebpackPlugin(), ]
- 方式二:直接在output中增加
clean:true
的配置项。
五. class
0. 基础使用
回顾并在原本的js-class中体验ts-class的用法。
class Person
//定义实例对象
name: string = 小智;
//static:定义类属性(静态属性)
static age: number = 18;
//readonly 表示一个只读属性
static readonly skill: string = "eat";
//定义方法,前置static就是类方法
sayHello()
console.log("Hello");
1. 构造函数&this
我们通过constructor
构造函数以及this
指向当前对象的实例。
class 皮卡丘
name:string;
power:number;
kind:string;
constructor(name:string,power:number,kind:string)
this.name = name;
this.power = power;
this.kind = kind;
bark()
alert("皮卡皮卡");
let pikaqiu = new 皮卡丘(YY的皮卡丘,100,electricity);
pikaqiu.bark();
2. 继承
还可以通过extends
实现继承。可以在类前面加sealed关键字禁止继承。扩展点:OCP原则。
//父类
class 宝可梦
name:string;//昵称
power:number;//力量
kind:string;//类别
constructor(name:string,power:number,kind:string)
this.name = name;
this.power = power;
this.kind = kind;
bark()
alert("宝可梦在叫~");
//子类
class 比雕 extends 宝可梦
//可以不写,但是如果在子类中写了构造函数,则必须通过super调用父类的构造函数
constructor(name:string,power:number)
super(name,power,flight);
fly()
console.log(`$this.name在飞~`);
//方法重写
bark()
console.log("渣渣~喳喳~");
3. 抽象
- 抽象类
上面的宝可梦是一个抽象的概念,我们可以创建比雕,但是不能直接创建宝可梦。所以我们通过abstract
关键字来声明这是一个抽象类。 - 抽象方法
不同的宝可梦叫声不一样,所以不能直接写出宝可梦的bark具体实现。需要声明它是抽象方法。
abstract class 宝可梦
//抽象方法只能定义在抽象类,且子类必须对其进行重写。
abstract bark():void;
4. 接口
接口是抽象的最高境界,抽到只剩下灵魂了~~
- 接口只定义对象的结构,而不考虑实际值。
- 所有的属性都不能有实际的值。
- 所有的方法都是抽象方法。
- 定义类时,可以使类去实现一个接口。
type myType
name:string;
sayHello()
//...
interface myInterface
name: string;
sayHello():void;
class MyClass implements myInterface
name: string;
sayHello()
console.log("大家好");
5. 属性封装
TS可以在属性前添加属性的修饰符,确保数据更加得安全。
- public:公有的,修饰的属性可以在任意位置访问修改默认值。(默认修饰符)
- private:私有属性,只能在类的内部进行访问。通过getter和settter可以被外部访问。
问题:为什么需要设置私有属性,然后再设置getter和setter呢?这不是多此一举吗?
理解:当一个类的属性可以被任意访问的时候,容易埋下隐患。通过getter和setter可以判断修改的值是否有效。
情景:比如宝可梦的力量power需要为正数。后续进行战斗,对方宝可梦的体力基于己方宝可梦的力量值进行扣除。若某处直接将其设置为负数,则会给对方宝可梦增加体力。如果通过setter呢?
(function()
class 皮卡丘
public name:string;
private power:number;
constructor(name:string,power:number)
this.name = name;
this.power = power;
getPower()
return this.power;
setPower(newPower:number)
if(newPower < 0 || newPower > 100 ) return error;
this.power = newPower;
//当然,也有语法糖
get name()
return this.name;
set name(value:string)
//judge is Valid ,then
this.name = value;
)();
除了private
和public
之外,还有protected修饰符。仅限当前类以及子类访问。
class A
protected num : number;
constructor(num:number)
this.num = num;
class B extends A
test()
console.log(this.num);
我们可以直接将属性定义在构造函数中
class C
constructor(public name:string,private age:number)
const c = new C (xxx,18);
6. 泛型
一个多元方程中的未知数x,只有代入其他具体的值,才能推断出它来。
问题:如果不确定输入的类型,但是要限制输出的类型和输入的类型一样,咋办?
function fn(a:any):any
return a;
以上是关于TypeScript学习笔记的主要内容,如果未能解决你的问题,请参考以下文章