【TypeScript】枚举类型和泛型的详细介绍

简介: 【TypeScript】枚举类型和泛型的详细介绍

枚举类型

枚举类型是为数不多的TypeScript特有的特性之一, JavaScript是没有的

枚举其实就是将一组可能出现的值,一个个列举出来,定义在一个类型中,这个类型就是枚举类型

枚举允许开发者定义一组命名常量,常量可以是数字、字符串类型;

枚举类型使用enum关键字定义, 建议枚举中定义的值使用大写

枚举我们常见的使用方式如下

enum Direction {
  LEFT,
  RIGHT,
  TOP,
  BOTTOM
}
function turnDirection(direction: Direction) {
  switch (direction) {
    case Direction.LEFT:
      console.log("转向左边")
      break;
    case Direction.RIGHT:
      console.log("转向右边")
      break;
    case Direction.TOP:
      console.log("转向上边")
      break;
    case Direction.BOTTOM:
      console.log("转向下边")
      break;
    default:
      const foo: never = direction
      break;
  }
}
// 测试
turnDirection(Direction.LEFT)
turnDirection(Direction.RIGHT)
turnDirection(Direction.TOP)
turnDirection(Direction.BOTTOM)

枚举类型默认是有值的,比如上面代码的枚举,默认值其实是这样的

enum Direction {
  LEFT = 0,
  RIGHT = 1,
  TOP = 2,
  BOTTOM = 3
}

当然,我们也可以给枚举其他值, 比如我们给LEFT一个值: 100

enum Direction {
  LEFT = 100,
  RIGHT,
  TOP,
  BOTTOM
}

这个时候LEFT后面的值如果没有设置值的话, 它们的默认值会从100进行递增, 相当于下面这样:

enum Direction {
  LEFT = 100,
  RIGHT = 101,
  TOP = 102,
  BOTTOM =103
}

我们也可以给他们赋值其他的类型

enum Direction {
  LEFT,
  RIGHT,
  TOP = "TOP",
  BOTTOM = "BOTTOM"
}

TypeScript泛型介绍

🎲泛型的基本使用

软件工程的主要目的是构建不仅仅明确和一致的API,还要让你的代码具有很强的可重用性

比如我们可以通过函数来封装一些API,通过传入不同的函数参数,让函数帮助我们完成不同的操作;

但是对于参数的类型是否也可以参数化呢?

什么是类型的参数化?

我们来提一个需求:封装一个函数,传入一个参数,并且返回这个参数;

如果我们是TypeScript的思维方式,要考虑这个参数和返回值的类型需要一致

// 传入number类型, 返回number类型
function foo(arg: number): number {
  return arg
}

上面的代码虽然实现了,但是不适用于其他类型,比如string、 boolean、 Person等其他类型

为了适用于其他类型, 我们可以定义为any类型

// 传入number类型, 返回number类型
function foo(arg: any): any {
  return arg
}

虽然any是可以的,但是定义为any的时候,我们其实已经丢失了类型信息

比如我们传入的是一个number,那么返回的也是是any类型, 我们并不是希望它返回number类型,我们希望返回number类型;

我们想要做到在函数中可以捕获到参数的类型是number,并且同时使用它来作为返回值的类型;

我们需要在这里使用一种特性的变量 - 类型变量( type variable),它作用于类型,而不是值

我们可以将它看做额外的一个参数;

它可以做到, 在定义这个函数时, 不决定这些参数的类型, 而是让调用者以参数的形式告知, 这里的函数参数应该是什么类型

function foo<Type>(arg: Type): Type {
  return arg
}

这里我们可以使用两种方式来调用它

  • 方式一:通过 <类型> 的方式将类型传递给函数;
foo<number>(123) // 传入number类型
foo<{name: string}>({ name: "chenyq" }) // 传入有name属性的对象类型
foo<number[]>([10, 20]) // 传入number类型的数组
  • 方式二:通过类型推导,自动推导出我们传入变量的类型:
  • 在这里会推导出它们是字面量类型的,因为字面量类型对于我们这个函数也是适用的
foo(50)
foo("aaa")
foo({ name: "kaisa" })

当然我们也可以传入多个类型

function foo<T, E>(arg1: T, arg2: E) {
  console.log(arg1, arg2)
}
foo<number, string>(123, "abc")

平时在开发中我们可能会看到一些常用的名称

T: Type的缩写,类型

K、 V: key和value的缩写,键值对

E: Element的缩写,元素

O: Object的缩写,对象

🎲泛型接口的使用

在定义接口的时候我们也可以使用泛型

// 定义泛型接口
interface IPerson<T1, T2> {
  name: T1
  age: T2
}
const p: IPerson<string, number> = {
  name: "chenyq",
  age: 18
}

泛型接口是没有类型推导的, 但是可以有默认值类型的

// 泛型接口定义默认类型
interface IPerson<T1 = string, T2 = number> {
  name: T1
  age: T2
}
const p: IPerson = {
  name: "chenyq",
  age: 123
}

🎲泛型类的使用

我们也可以编写一个泛型类

class Point<T> {
  x: T
  y: T
  z: T
  constructor(x: T, y: T, z: T) {
    this.x = x
    this.y = y
    this.z = z
  }
}
// 泛型类是可以自动推导类型的
const p1 = new Point("1.22", "3.56", "7.32")
// 也可以自己指定类型, 有下面两种方式
const p2 = new Point<number>(10, 20, 30)
const p3: Point<string> = new Point("1.22", "3.56", "7.32")

🎲泛型的类型约束

有时候我们希望传入的类型有某些共性,但是这些共性可能不是在同一种类型中

比如string和array都是有length的,或者某些对象也是会有length属性的, 但是此时使用泛型, 编译阶段是会报错的, 因为不能保证泛型的所有类型都是有length属性的;

43c1a420ebd6407297457477a9a25ad7.png

那么只要是拥有length的属性都可以作为我们的参数类型,而没有length属性的不允许作为参数, 那么应该如何操作呢?

我们可以使用接口定义一个对象类型, 对象类型要求必须有length属性, 在让泛型继承自这个接口

interface ILength {
  length: number
}
// 泛型继承自接口
function getLength<T extends ILength>(arg: T) {
  console.log(arg.length)
}
// 测试
// getLength(123) // 123没有length无法传入
getLength("abc") // 3
getLength([10, 20, 30]) // 3
getLength({ length: 10 }) // 10


相关文章
|
6天前
|
JavaScript 前端开发 编译器
TypeScript【泛型1、泛型2、声明合并、命名空间 、模块1、模块2、声明文件简介】(五)-全面详解(学习总结---从入门到深化)
TypeScript【泛型1、泛型2、声明合并、命名空间 、模块1、模块2、声明文件简介】(五)-全面详解(学习总结---从入门到深化)
69 0
|
6天前
|
JavaScript 编译器
TypeScript中泛型在函数和类中的应用
【4月更文挑战第23天】TypeScript的泛型在函数和类中提供了灵活性,允许处理多种数据类型。了解泛型是掌握TypeScript类型系统的关键。
|
6天前
|
JavaScript 安全 前端开发
【TypeScript技术专栏】TypeScript泛型编程技巧
【4月更文挑战第30天】TypeScript的泛型编程允许编写适应多种数据类型的函数和类,提高代码复用性。基本概念包括在声明函数、接口或类时使用类型参数。示例:泛型函数`identity&lt;T&gt;`、泛型接口`GenericIdentityFn&lt;T&gt;`和泛型类`GenericNumber&lt;T&gt;`。技巧包括类型推断、泛型约束和泛型数组。在实际开发中,泛型用于创建通用库、装饰器和中间件,提升代码灵活性和复用性。
|
6天前
|
JavaScript 安全 索引
TypeScript泛型和类型体操
泛型和类型体操(Type Gymnastics)是 TypeScript 中高级类型系统的重要组成部分。它们提供了强大的工具和技巧,用于处理复杂的类型操作和转换。
|
6天前
|
JavaScript 前端开发 编译器
TypeScript【泛型1、泛型2、声明合并、命名空间 、模块1、模块2、声明文件简介】(五)-全面详解(学习总结---从入门到深化)(下)
TypeScript【泛型1、泛型2、声明合并、命名空间 、模块1、模块2、声明文件简介】(五)-全面详解(学习总结---从入门到深化)
32 0
TypeScript【泛型1、泛型2、声明合并、命名空间 、模块1、模块2、声明文件简介】(五)-全面详解(学习总结---从入门到深化)(下)
|
6天前
|
JavaScript
TypeScript【泛型1、泛型2、声明合并、命名空间 、模块1、模块2、声明文件简介】(五)-全面详解(学习总结---从入门到深化)(上)
TypeScript【泛型1、泛型2、声明合并、命名空间 、模块1、模块2、声明文件简介】(五)-全面详解(学习总结---从入门到深化)
38 0
|
6天前
|
JavaScript 前端开发
【面试题】 面试官:说说你对 TypeScript 中枚举类型的理解?应用场景?
【面试题】 面试官:说说你对 TypeScript 中枚举类型的理解?应用场景?
|
6天前
|
JSON JavaScript 前端开发
TypeScript:得泛型者,得天下
TypeScript:得泛型者,得天下
|
6天前
|
存储 JavaScript 前端开发
如何在 TypeScript 中使用泛型?
如何在 TypeScript 中使用泛型?
|
6天前
|
JavaScript 编译器
TypeScript基础(五)泛型
在编程中,我们经常会遇到需要处理不同类型数据的情况。为了提高代码的复用性和灵活性,TypeScript引入了泛型的概念。泛型可以让我们在定义函数、类或接口时,不预先指定具体的类型,而是在使用时再指定类型。本文将详细介绍TypeScript中泛型的使用方法和技巧。
40 0