likes
comments
collection
share

对TS的重新学习(一)

作者站长头像
站长
· 阅读数 19

前言

在较早之前因为一个项目的原因了解过TS,只是知道一个大概,从来没有系统的学习如何使用,于是决定趁着现在将TS这门语言正式的学习一下。

开始前的准备工作🚴🚴

在学习开始之前,我们搭建一些基础的环境,这样才可以开始我们的学习

npm i typescript -g

首先我们需要全局的安装typescript,这样才可以使用TS。

当我们安装完成之后,执行以下命令来查看版本

tsc -v

如果可以正常的打印出版本号那么就代表我们安装成功

之后我们再接着安装一下这几个npm包来让我们可以方便的使用TS(不安装也可以,但是每一次需要将TS转换为JS文件,然后去执行JS文件),安装之后我们只需要每次执行ts文件就可以了。

npm i ts-node -g
npm i @types/node -D 

然后我们以后就可以使用ts-node命令来直接编译TS文件,这样就方便了很多,这样我们就可以正式的开始学习TS了。

TS的语言类型⛹️‍♀️⛹️‍♀️

基础类型

这部分比较容易理解,例如

let str:string="xiaoming"
let num:number=1
let bool:boolean=true
let c: void = undefined;

向上面提及的string,number,boolean,void都属于基础类型,类似的包括像 undefined、null、symbol、bigint这些也都是基础类型这样做的好处就是当我们输入与预先定义的类型不同的值的时候,就会报错,这样也算是帮助我们排除错误了。

any和unknown类型

在学习这一块知识之前我们先了解一下类型:

any 任意类型 unknown 不知道的类型

  • top type 顶级类型 any unknown
  • Object
  • Number String Boolean
  • number string boolean
  • 1 "小民" false
  • never

这是所有类型的一个层次关系,处在最高处的anyunknown就属于是顶级类型,往下就依次是Object等这些类型了

然后我们再来了解一下any和unknown的区别:

  • any类型可以给任何值赋值,也可以被任何类型的值赋值

比如:

let a:any=1,
let b:number=3
a=b;
b=a;

这些操作都是可以的,即无论是将a的值赋值给b还是将b的值赋值给a都是被允许的。

  • unknown类型只能同类型赋值或者被赋值(不能把值赋给其他)
let a:unknown=1
let b:number=6
let c:unknown="sdde"
a=c;//这个被允许
c=a;//这个被允许
b=a//这个操作是不被允许的,会报错

我的理解是a变量已经是未知类型的了,那么怎么能把未知类型付给其他已知类型呢。

Object和object的区别

作为初学者在开始学习的时候,我们时常对这两中类型分不清楚,他们之间到底有什么区别呢?

首先Object与原型链有关,因为原型链的顶端就是Object或者function,在TS中他就代表了所有的类型。

那么object呢?他其实代表的就是非原始类型的其他类型比如除了像string,number,boolean这些,它支持引用类型,比如数组,对象,函数等等

let x: object = [];
let x1: object = {};
let x2: object = () => 2;
------------------
let a1: Object = 2;
let a2: Object = "2";
let a3: Object = () => 12;

接口和对象类型

首先接口的使用场景就是为了限制对象中的值的类型,比如下面这样:

interface sscas {
  name: string;
}
let obj: sscas = {
  name: "sds",
};

注意这个限制的对象里面不能少属性,但也不能增添属性,必须和定义的接口中的属性完全一致(包括属性名称和值的类型)。

但是有时候我们像将某些属性设置为可选的那该怎么做呢?我们可以在定义的属性值后面加上问号就如同下面这样:

name?:string

这样就表明这个属性值是可选的了。

还有一种情况,我们想要将对象中的某个属性的值设置为只读类型不能进行修改,比如后端传给前端的id之类的值,我们该如何设置呢?

我们需要在接口中的属性前面加上关键字readonly,这样就是只读了。

interface sscas {
   readonly id: number;
}

这样做之后当我们想要修改对象中的id值就会报错。

值得注意的是当在一个文件中存在重名的接口时,会进行合并,比如下面这样

interface sscas {
  name: string;
}
interface sscas{
  age:number
}
----------------------就相当于时下面这样
interface sscas{
 name: string;
 age:number
}

有的时候比如后端返回给我们的数据类型不是严格是某个类型,比如我只想要获取其中的name和age属性,但是又不能给其他属性严格限制死,这个时候我们该如何做呢?可以参考下面这样操作。

interface sscas {
  name: string;
  age: number;
  [propName: string]: any;
}
let obj: sscas = {
  name: "sds",
  age: 22,
  sd: 23,
  sdrf: "231321",
};

我们可以在原来的接口上面增添[propName: string]: any;这样的一行代码,这样做就是将所有值的类型后包含在内了,无论值是字符串还是数字还是数组等等类型都被包含在内。这样我们就可以读取自己想要的数据,又可以定义返回的数据类型。

接口的继承

其实这部分和java有些相似,具体代码就是下面这样

interface sscas extends B {
  name: string;
  age: number;
}
interface B {
  id: number;
}
let obj: sscas = {
  id: 1,
  name: "sds",
  age: 22,
};

其实就是接口sscas继承了接口B上面的内容,这样我们在使用sscas的时候,就需要新增加id这个属性,值的类型就是number。

接口定义函数类型

我们使用接口还可以定义函数的类型,具体就是下面代码的写法。

interface Fn {
  (name: string): number[];
}
const fn: Fn = function (name: string) {
  return [1];
};

在这个代码里面我们将fn约束为Fn类型,我们必须严格约束函数中传入的参数的值的类型,并且还约束返回的值类型,否则就会检验报错。

数组类型

我们在使用数组的时候,也可以定义类型,下面就让我们来看一下如何定义吧。

首先是最基本的方式

let arr: number[] = [1, 2, 3];
let arr1: string[] = ["sd", "sded"];

这两种方式是最基本的方式,我们可以在基本数据类型后面加上[]来表示数组的形式,这样就对数组中的数据类型进行了限制。

当然我们也可以使用泛型,这个后面会着重讲解,我们先来了解一下:

let arr: Array<number> = [1, 2, 3];
let arr1: Array<string> = ["sd", "sded"];

这里面的Array就代表数组,然后<>里面的内容就代表数组中的值,那么我们该如何定义二维的数组呢?

其实对于二维的数组的定义也是很简单,下面是代码演示:

let arr: number[][] = [[1], [2], [3]];
let arr2: Array<Array<number>> = [[1], [2], [3]];

以上就是对于二维数组的定义的两种方式,个人比较推荐第一种因为比较的直观清晰

如果我们的数组中存的内容是对象呢?那该如何做呢?

其实这和我们之前学的接口(interface)结合了起来。下面进行代码演示:

interface Arr {
  name: string;
  age?: number;
}
let arr2: Arr[] = [{ name: "see", age: 20 }];

当然如果一个数组中有许多不同类型的数据,没有办法集中的统一规定,这个时候我们可以使用any来定义。

let arr:any[]=["sdas",62,true]

扩展部分:

当然实际如果我们还可能和函数结合起来使用,比如下面这种:

function a(...args: number[]) {
    //let a:any[]=arguments  这种方式是错误的,因为arguments是伪数组,没有数组那么多的方法
  let a: IArguments = arguments;
  console.log(a);
}
a(1, 2, 3);

在TS中还提供了内置的一些类型,比如这个Arguments这个类型就是为arguments准备的,其实这个IArguments的实现原理也是比较好理解,他也是向我们定义接口那样定义的,例如:

function a(...args: number[]) {
  let a: A = arguments;
  console.log(a);
}
a(1, 2, 3);
interface A {
  callee: Function;
  length: number;
  [index: number]: any;
}

替换成这种形式也是可以的,其实他的实现原理就是这样做的。

小结🥝🥝

好的,那么本次TS就先讲解到这里,这是第一部分的内容,后续部分我会继续更新