TS的重新学习(三)

前言

大家好,多日未见,这一次我们继续进行TS的学习,今天讲述的东西可能稍微有些难懂(笔者刚开始学习的时候也是感觉困难)

泛型⚡️⚡️

泛型个人认为是TS中非常重要的一部分,因此我觉得如果泛型学习的差不多,那么TS才叫真正意义上的学好。

这部分内容对于学习过java的同学相信并不陌生

什么是泛型

在学习之前我们先来了解泛型的定义:泛型是指附属于函数,类,接口,类型别名之上的类型,当某个函数的参数,返回值和内部使用的类型无法确定的情况下,就可以使用泛型进行约束。

如何定义泛型呢?

其实也很简单我们可以在函数名称之后加上,这个T就是泛型名称,当然你可以随意的定义名称,我们在向函数传递参数的时候也可以这样传递

举一个例子

php 复制代码
function fn<T>(args: T): T {
  return args;
}
fn<string>("hello");

这样T的类型就被限制在字符串类型中,如果我们传递的类型不是string类型的,TS就会报错。

接口中使用泛型

当然我们不仅可以在函数中使用泛型,我们同样可以在接口中定义泛型,我们来看下面的这个例子

typescript 复制代码
interface idfuc<T, Y> {
  id: (value: T) => T;
  name: (value: Y) => Y;
}
let obj2: idfuc<number, string> = {
  id(value) { return value; },
  name(value) { return value; },
};

这里我们在接口中定义使用了泛型,我们进行了类型的约束,这样做的目的就是我们可以提高这个接口的复用性,不事先定义好,而是可以灵活的控制。更加的方便灵活。

类中使用泛型

同样我们在类中也可以使用泛型约束,就比如下面的这个例子:

ini 复制代码
class Article<T, Y> {
  id: T;
  author: Y;
  constructor(id: T, author: Y) {
    this.id = id;
    this.author = author;
  }
  getAuthor<Y>(name: Y) {
    console.log(name);
  }
}
const article = new Article(12, "de");

这样当我们传入相应的值的时候,TS的类型推断会给我们自动的推断,判断传入的值的类型,这里面我们传递id的值为number类型,传入author的值的类型为string类型,TS就可以自动的给我们推断出来,包括上面举得函数的例子也是如此fn("hello"),如果我们不写,那么TS还是会自动推断为string类型。这就是TS类型推断的好处。

数组泛型

在数组中使用泛型个人认为不多见,下面我们举个例子

ini 复制代码
let arr: Array<number> = [1, 2, 3, 4] ===  arr:number[]=[1,2,3];

泛型约束🌾🌾

  • 因为在默认情况下T可以代表任何类型,这就导致了无法访问任何属性,所以我们有时候需要进行类型的约束

比如下面这种情况:

matlab 复制代码
function getlength<T>(str:T){
   console.log(str.length);
}
getlength("sdad")

这个时候编译器就会报错,提示T这个类型上面并不存在这个属性,当然我们可以通过判断str的类型来决定是否打印length,但是这样做太过于繁琐,而且使用场景有限,因此泛型约束就应运而生。

那么进行类型约束主要有两种方式:

  • 使用extends关键字进行类型的约束
  • 进行更加具体的类型定义。

extends关键字

注意这里面的extends和我们之前学习的类中的extends不是一个含义,这里的可以理解为约束于,而之前学习的是继承的含义

这里面我们使用第一种方式来进行

javascript 复制代码
function getlength<T extends String>(str: T) {
  console.log(str.length);
}
getlength("sdsd");

如果我们采取这种方式就相当于是将T类型约束为String类型,这样可以获取String上面的所有属性,但同时我们只能传入string类型的值,而且如果我们不需要这么多属性,我们其实可以这样做:

typescript 复制代码
interface IsLength {
  length: number;
}
function getlength<T extends IsLength>(str: T) {
  console.log(str.length);
}

我们可以自己定义接口,然后泛型约束为这个接口以内,这个含义就是传入的参数中的属性必须有length这一项才可以满足需求,这样我们传入数组这种有长度的值的时候也可以满足需求。

第二种方式种提到的更加具体的类型定义是什么意思呢?

比如如果我们想要约束传入的值是一个数组,我们就可以这样做:

matlab 复制代码
function getlength<T>(str:T[]){
   console.log(str.length);
}

这样如果我们传递的不是数组,那么此时就会报错。

keyof关键字

这个部分是对类型约束的补充,也是很重要,那么这个关键字是有什么用呢?

这个关键字可以获取对象中的key值

ini 复制代码
let obj = {
  name: "sda",
  sex: "男",
};
type Key = keyof typeof obj;

这里就可以获取Key的类型为联合类型,为"name"|"sex",这里面type将他推断为联合类型。

那他的使用场景是什么呢?比如现在我们需要获取一个对象中的某个值,我们就可以使用这个关键字

typescript 复制代码
interface Data {
  name: string;
  age: number;
  sex: string;
}
function ob<T extends Data, K extends keyof T>(obj: T, key: K) {
  return obj[key];
}

这里面我们首先将T约束为Data类型,其次我们这里的key值约束为传递的T中的属性值,这样我们在返回obj[key]的时候才不会报错,否则TS会认为这是不安全的而报错。而且这样做了之后我们在使用函数的时候,传递第二个值会有提示,还是很爽的。

内置工具类型🍆🍆

Record

Record<K extends keyof any, T>这个工具类型的作用是什么呢?

首先我们要明白K extends keyof any的含义,这部分也是用到了类型约束,表明传入的K的类型只能为string|number|symbol 这几个类型中的一个,

用途:Record 工具类型用于创建一个对象类型,其中键为 Key 类型的值,值为 Type 类型的值。

举一个例子:

typescript 复制代码
interface E {
  title: string;
  id: number;
}
type article = "home" | "other" | "about";
type ded=record<article,E>
//等价于
{
  home:{title:string,id:number},
  other:{title:string,id:number},
  about:{title:string,id:number}
}

这样演示一下应该就比较清楚了,其实就是创造了一个对象类型,使用这个工具可以更加的方便,不需要我们在手动的定义了

Partial

Partial

用途:Partial 工具类型将泛型类型的所有属性都变为可选属性。

举一个例子:

ini 复制代码
interface Person {
  name: string;
  age: number;
}
type PartialPerson = Partial<Person>;
// PartialPerson 的类型是 { name?: string; age?: number; }

这样做就将全部的属性上面加上可选,不需要我们在重复的定义,节省时间,其实内部实现也是比较容易理解的

ini 复制代码
type Partial<T> = { 
  [P in keyof T]?: T[P];
};

首先通过keyof获取传递进来的对象类型中的属性名,然后通过in关键字进行遍历,其实和for in很像,[[P in keyof T]]代表的就是每次遍历的属性名然后T[P]就是属性值,在加上?就实现了功能

Pick

Pick<T,K>

用途:Pick 工具类型用于从泛型类型中选取指定属性键集合 Keys 对应的属性。

ini 复制代码
interface Person {
  name: string;
  age: number;
  address: string;
}
type PersonInfo = Pick<Person, 'name' | 'age'>;
// PersonInfo 的类型是 { name: string; age: number; }

从字面上的意思理解就是挑选,其实就是从对象中挑选一部分来作为新的类型。

Omit

Omit<T,K>

用途:Omit 工具类型用于从泛型类型中排除指定属性键集合 Keys 对应的属性。

ini 复制代码
interface Person {
  name: string;
  age: number;
  address: string;
}
type PersonWithoutAddress = Omit<Person, 'address'>;
// PersonWithoutAddress 的类型是 { name: string; age: number; }

比如有些时候我们可能需要排除一些属性,可以利用大部分属性,又不想要重新在写,这个时候就可以使用这个内置工具类。

小结

今天我们学习了一下泛型以及相关的知识,相信大家还是会有收获的。

相关推荐
生椰拿铁You5 分钟前
09 —— Webpack搭建开发环境
前端·webpack·node.js
狸克先生17 分钟前
如何用AI写小说(二):Gradio 超简单的网页前端交互
前端·人工智能·chatgpt·交互
sinat_3842410919 分钟前
在有网络连接的机器上打包 electron 及其依赖项,在没有网络连接的机器上安装这些离线包
javascript·arcgis·electron
baiduopenmap31 分钟前
百度世界2024精选公开课:基于地图智能体的导航出行AI应用创新实践
前端·人工智能·百度地图
loooseFish39 分钟前
小程序webview我爱死你了 小程序webview和H5通讯
前端
小牛itbull43 分钟前
ReactPress vs VuePress vs WordPress
开发语言·javascript·reactpress
请叫我欧皇i1 小时前
html本地离线引入vant和vue2(详细步骤)
开发语言·前端·javascript
533_1 小时前
[vue] 深拷贝 lodash cloneDeep
前端·javascript·vue.js
guokanglun1 小时前
空间数据存储格式GeoJSON
前端
GIS瞧葩菜1 小时前
局部修改3dtiles子模型的位置。
开发语言·javascript·ecmascript