TypeScript学习之路
🚀🚀掘金---碰磕,分享自己的学习日志
⛅⛅多云
✊✊生活不能等待别人来安排,要自己去争取和奋斗;而不论其结果是喜是悲,但可以慰藉的是,你总不枉在这世界上活了一场。有了这样的认识,你就会珍重生活,而不会玩世不恭;同时,也会给人自身注入一种强大的内在力量。——路遥《平凡的世界》
📅2022/5/27
TypeScript增加了什么
类型
支持ES的新特性
添加ES不具备的新特性
丰富的配置选项
强大的开发工具
安装
全局安装
#
npm i -g typescript
基本类型
| 类型 | 例子 | 描述 |
|---|---|---|
| array | [1,2,3] | 数组 |
| tuple | [4,5] | 元组,ts新增类型,固定长度数组 |
| enum | enum[A,B] | 枚举,ts新增类型 |
| number | 1,213,-1 | 任意数字 |
| string | 'hi','你好' | 任意字符串 |
| boolean | false,true | 布尔型 |
| 字面量 | 其本身 | 限制变量的值就是该字面量的值 |
| any | * | 任意类型 |
| unknown | * | 类型安全的any |
| void | 空值 | 没有值(undefined) |
| never | 没有值 | 不能是任何值 |
| object | {name:'碰磕'} | 任意的对象 |
-
类型声明
- 语法
- let 变量:类型=值
-
number
//声明一个变量a指定类型为number let a: number; //在之后只能给a赋值number类型 a=12 // a='12';//该代码会报错.... -
string
//声明一个变量b指定类型为string let b: string; //在之后只能给b赋值string类型 b='13' // b=12;//该代码会报错.... -
boolean
let b:boolean=true -
字面量
//使用字面量进行类型声明 let s1: 10; s1=10; //s1=11; //会报错 -
any
//any任意类型,设置该类型后相当于对该变量关闭了ts类型检测 let s3:any; //使用ts不建议使用 s3=1; s3='123'; s3=false; -
unknown
// unknown 未知类型 let s4:unknown; s4=123; s4='pengke'; -
any与unknown的区别
any类型可以赋值给任意变量
unknown类型不可直接赋值给任意变量
unknown 实际上是安全的any类型
-
void
//void表示空值,以函数为例表示没有返回值的函数 function fn1() :void{ } -
never
//never表示没有值 function fn2() :never{ throw new Error('报错.') } -
object
//object 表示一个对象 let obj:object; obj={};{}可用来指定对象中可以包含哪些属性
语法: {属性名:类型......}
在属性名后边加?表示属性是可选的
let obj1: {name:string,age?:number};
obj1={name:'孙策'}
//[sxname:string]:any表示任意字符串的属性名,类型是any....
let obj2:{name:string,[sxname:string]:any}
obj2={name:'碰磕',age:12,address:'地址'}
-
array
-
数组的声明
-
类型[]
-
Array<类型>
//指定类型的数组 //string[]表示字符串数组 let sz: string[]; sz=['a','b','c'] let sz2: Array<string> sz2=['a','b','c']
-
-
-
tuple(元组)
语法:[类型,类型....]
let arr:[string,number]; arr=['sd',11]; -
enum(枚举)
enum Gender{ boy=0, gril=1 } let i:{name:string,gender:Gender}; i={ name:'碰磕', gender:Gender.boy }
类型断言
可以用来告诉解析器变量的实际类型
语法 :
变量 as 类型
<类型> 变量
let s4:unknown;
let s5:string;
s4=123;
s4='pengke';
s5 =s4 as string;
s5=<string>s4
拓展
-
ts可以规定参数类型
-
举个例子
-
//ts可以规定参数类型 function sum(a:number,b:number){ return a+b; }
-
-
可以使用|连接多个类型(联合类型)
-
举个例子
-
let s2: "male"| "nihao" s2="male"; s2="nihao"; //s2="sda"//会报错
-
-
&表示与的意思
-
举个例子
-
let j:{name:string} & {age:number}; j={name:'s',age:1}
-
-
类型的别名
-
举个例子
-
type myType=1|2|3|4|5|6; let k:myType; let l:myType; k=1 l=5
-
编译
语法:
tsc 文件名
监视文件改动进行自动编译
tsc 文件名 -w
编译整个项目
-
创建配置文件tsconfig.json
-
执行命令
tsc -w
配置文件详解
tsconfig.json是ts编译器的配置文件,ts编译器可以根据它的信息来对代码进行编译
- "include"用来指定哪些ts文件需要被编译
路径:**表示任何目录,*表示任何文件
- "exclude"用来指定哪些ts文件不需要被编译
默认值:["node_modules","bower_components","jspm_packages"]
- "extends"定义被继承的配置文件
- "files":"指定被编译的文件列表"例如:[app.ts,server.ts.......]
-
"compilerOptions" 编译器的选项
-
常用子选项
-
target:指定编译成的es版本
"target": "es6",
-
module指定要使用的模块化的规范
"module": "es6",
-
lib用来指定项目中要使用的库
"lib": []
-
outDir用来指定编译后文件所在的目录
"outDir": "./dist",
-
outFile将代码合并一个文件(前提module必须是amd或者是system)
"outFile": "./dist/ok.js"
-
是否对js文件进行编译,默认是false
"allowJs": false,
-
是否检查js代码是否符合语法规范,默认值:false
"checkJs": false,
-
是否移除注释,默认false
"removeComments": false,
-
不生成编译后的文件,默认false
"noEmit": false,
-
当有错误时不生成编译后的文件,默认false
"noEmitOnError": false,
-
所有严格检查的总开关
"strict": true,
-
用来设置编译后的文件是否使用严格模式,默认false
"alwaysStrict": true,
-
不允许隐式的any类型
"noImplicitAny": false,
-
不允许不明确类型的this
"noImplicitThis": false,
-
严格检查空值
"strictNullChecks": false,
-
-
使用webpack打包ts
- 安装依赖
npm i -D webpack webpack-cli typescript ts-loader //安装依赖
-
初始化项目
npm init -y -
新建文件夹webpack.config.js并编写该配置文件
/** * webpack 配置文件 */ const path=require('path'); module.exports={ //调试时使用development开发模式 //打包时使用production生产模式 mode : 'development', entry: path.join(__dirname,'./src/index.js'), //__dirname表示当前目录当前路径 output: { path: path.join(__dirname,'./dist'), filename:'bundle.js', },//出口 module:{ rules:[ { //指定规则生效的文件 test:/\.ts$/, //使用的loader use:'ts-loader', //要排除的文件 exclude:/node_modules/ } ] } } -
创建ts编译器的配置文件tsconfig.json
{ /* tsconfig.json是ts编译器的配置文件,ts编译器可以根据它的信息来对代码进行编译 */ "include": [ "./src/**/*" ], /* "compilerOptions" 编译器的选项 */ "compilerOptions": { //target:指定编译成的es版本 "target": "es6", //module指定要使用的模块化的规范 "module": "es6", "strict": true } } -
编写package.json
-
"scripts": { "test": "echo \"Error: no test specified\" && exit 1", "build":"webpack" }, //在scripts中加上"build":"webpack" -
打包
npm run build
直接运行ts
//下载
npm install -g ts-node
//运行
ts-node 文件名
类
类的定义
- 通过关键词class进行定义
- readonly代表只读属性
- static表示静态属性,可直接通过类.属性名(方法名)获取
//使用class关键字定义一个类
/**
* 类中有属性和方法
*/
class Person{
//定义属性 readonly表示只读
// readonly name:string='孙悟空';
//static静态属性通过类.属性名可直接获取
// static age:number=12;
name="碰磕";
age=18;
//定义方法
sayHello(){
console.log("你们好");
}
}
const per=new Person();
console.log(per);
per.sayHello();
构造函数
通过关键词constructor定义构造函数
构造函数会在创建时调用
下方代码演示了有参构造函数.....
class Dog{
name='旺财';
age=3;
bark(){
console.log(this.name);
}
//constructor 被称为构造函数
//构造函数会在创建时调用
constructor(name:string,age:number){
console.log("我是构造函数..");
this.name=name;
this.age=age;
}
}
const dog=new Dog('狗1',12);
const dog2=new Dog('狗2',32);
const dog3=new Dog('狗3',24);
console.log(dog,dog2,dog3);
dog2.bark();
继承、重写
关键词:extends
如果子类中添加了和父类相同的方法,子类的方法会覆盖父类的方法....(重写)
下方代码示例:
//定义一个Animal类
class Animal{
name:string;
age:number;
constructor(name:string,age:number){
this.name=name;
this.age=age;
}
sayhello(){
console.log("动物...");
}
}
class Dog extends Animal{
run(){
console.log(this.name+"跑了");
};
//如果子类中添加了和父类相同的方法,子类的方法会覆盖父类的方法....
sayhello(): void {
console.log("汪汪汪...");
}
}
const dog=new Dog('小花',12);
console.log(dog);
dog.sayhello();
dog.run();
class Cat extends Animal{
}
const cat=new Cat('猫猫',22);
console.log(cat);
cat.sayhello();
super关键字
- 在类的方法中super代表父类
- 如果在子类中写了构造函数,必须调用父类的构造函数super(属性)
class Animals{
name:string;
constructor(name:string){
this.name=name;
}
sayhello(){
console.log("你们好...");
}
}
class Pig extends Animals{
age :number;
// 如果在子类中写了构造函数,必须调用父类的构造函数super(属性)
constructor(name:string,age:number){
super(name);//调用父类的构造函数
this.age=age;
}
sayhello(){
//在类的方法中 super表示当前类的父类
super.sayhello();
}
}
const pig=new Pig('小猪猪',109);
pig.sayhello();
抽象类
关键词: abstract
- 通常用来被继承的类
- 抽象类可以有抽象方法
- 抽象方法代表子类中必须实现该抽象方法
//abstract表示抽象类(不能用来创建对象)
//通常用来被继承的类
//抽象类可以有抽象方法
abstract class Animals1{
name:string;
constructor(name:string){
this.name=name;
}
//定义一个抽象方法
//只能定义在抽象类中
/**代表子类中必须实现该抽象方法... */
abstract sayhello():void;
}
class Pig1 extends Animals1{
sayhello(): void {
console.log("噜噜噜..");
}
}
const pig1=new Pig1('小猪猪');
pig1.sayhello();
接口
关键词:interface
- 接口用来定义一个类的结构,可以定义应该包含哪些属性方法
- 同时接口可以当作类型声明使用
- 两个一样的接口编写不会覆盖,而会合并
- 接口可以在定义类的时候去限制类的结构
* 接口中的所有属性都不能有实际值,
* 只能定义对象的结构,而不考虑实际值
* 在接口中,所有的方法都是抽象方法
type myType={
name:string,
age:number
};
/*
接口用来定义一个类的结构,可以定义应该包含哪些属性方法
同时接口可以当作类型声明使用
*/
interface myInterface{
name:string,
age:number;
}
interface myInterface{
sex:string
}
//两个一样的接口编写不会覆盖,而会合并
const obj:myInterface={
name:'碰磕',
age:11,
sex:'男'
};
/**
* 接口可以在定义类的时候去限制类的结构
* 接口中的所有属性都不能有实际值,
* 只能定义对象的结构,而不考虑实际值
* 在接口中,所有的方法都是抽象方法
*/
interface myjk{
name:string;
sayHello():void;
}
实现接口implements
关键词:implements
实现接口也就是使类满足接口的要求
class Myclass implements myjk{
name:string;
constructor(name:string){
this.name=name;
}
sayHello(): void {
console.log("接口....");
}
}
属性的封装
由于可以直接修改且访问属性值,所以我们需要封装属性进行安全性提高...
Ts可以在属性前添加属性修饰符
- public 公共的
- private私有的
- --通过类中添加方法使得可以被外部访问
- protected受保护的(只能在当前类或当前类的子类中访问修改)
class Chidren{
private _name:string;
private _age:number;
constructor(name:string,age:number){
this._name=name;
this._age=age;
}
//定义一个方法获取name属性
getName(){
return this._name;
}
setName(val:string){
this._name=val;
}
getAge(){
return this._age;
}
setAge(val:number){
//可以判断年龄是否合法
if(val>=0){
this._age=val;
}
}
}
const r1=new Chidren('碰磕',22);
r1.setName('pengke')
console.log(r1.getName());//pengke
Ts中设置getter方法的方式
get name(){
console.log('get name()执行了');
return this._name;
}
set name(val){
this._name=val;
}
get age(){
console.log('get age()执行了');
return this._age;
}
set age(val){
if(val>=0){
this._age=val;
}
}
这样就可以直接访问属性赋值了...
r1.name--->就可以得到name的值
泛型
顾名思义即是不确定的类型用泛型
在定义函数或者是类时,如果遇到类型不明确就可以使用泛型
- 泛型可以同时指定多个
- 泛型可以不仅可以使用在函数上还可以在类里使用
- 泛型能指定继承接口
/**
* 在定义函数或者是类时,如果遇到类型不明确就可以使用泛型
*/
function fn<T>(a:T) :T{
return a;
}
let val1=fn(12312);//不指定泛型类型,TS可以自行推断
let val2=fn<string>('sd');//手动指定泛型类型
console.log(val1,val2);
//泛型可以同时指定多个
function fn2<T1,T2>(a:T1,b:T2):T1{
console.log(a,b);
return a;
}
fn2<number,string>(10,'碰磕');
interface Inter{
length:number;
}
//表示该泛型需要是该接口的实现类(子类)
function fn3<T extends Inter>(a:T) :number{
return a.length;
}
fn3('123');
class Mycls<T>{
name:T;
constructor(name:T){
this.name=name;
}
}
const cs=new Mycls<string>('碰磕');
以上内容即可对Ts大致了解了 My Learning Route😁😁😁