美文网首页
typescript枚举类的封装,继承Array时报错Sprea

typescript枚举类的封装,继承Array时报错Sprea

作者: mudssky | 来源:发表于2023-06-09 02:22 被阅读0次

写了好几年的前端代码,但是面向对象相关的东西基本上很少用到。

其实我一直觉得js的面向对象是残疾的,对比java,C#之类的语言。。。 而且还还有很多坑,比如this的问题。基本上现在我就几乎不会用到this了,所以也就碰不到this的问题。。

有了typescript以后,算是好用一些,能帮你避免一些问题。也支持private修饰符等等很多原生js没有的功能。

最近我在封装枚举类的时候碰到了问题,这个需求比较常见,后端经常定义一些各种状态的枚举,然后数据库里面都是存的数字的字符串。因此返回前端的数据也是各种数字,所以前端需要定义这些状态,一开始我都是直接用一个字典来存的。创建了两种字典,一种是键用数字,一种是值用数字。。。定义完一种,另一种调用lodash的方法 _.mapKey就得到了。

我在网上刷到过相关的文章,有的人封装了工具函数,用来获得各种各样的枚举满足不同的需求,有的人用类来封装继承了Array。都是用typescript添加了类型提示。。。

我发现继承Array来实现不错,因为这样就能继承array的方法了。可以当作正常的数组来用,而且通过对象的方法来获取对应的值,IDE的提示更友好,用起来也舒服。

参考网上的代码继承数组,结果使用的时候遇到了报错//TypeError: Spread syntax requires ...iterable[Symbol.iterator] to be a function

export interface EnumArrayObj {
  value: number | string
  label: string
}

export class EnumArray<
  T extends readonly EnumArrayObj[],
> extends Array<EnumArrayObj> {
  constructor(list: T) {
    super(...list)
  }
}

export const sexEnum = new EnumArray([
    {
      label: '男',
      value: '1',
    },
    {
      label: '女',
      value: '2',
    },
  ] as const),

console.log(
  'test enum filter',
  sexEnum.filter((item) => {
    return item.label === '女'
  }),
) //TypeError: Spread syntax requires ...iterable[Symbol.iterator] to be a function

在网上搜这个报错基本上搜不到什么东西。。。

问chatGPT和new bing,也不太行。

最后我自己解决了。

既然报错的是...扩展运算符,那么不用这个就行了。。。

一开始我想到了Array.from,但是出现了其他报错,并没有解决问题。

后面又想到是不是没有实现迭代器的接口导致的。。。

最后还是解决了。因为我想到super其实就是Array的构造器,但是ts类型提示的是,参数是(length:number)

也就是创建一个长度为length的数组,并且初始值都是undefined

所以,直接用for循环给这个数组赋值就可以了。这样就不会用到扩展运算符。。。

最终我实现的代码如下

// 枚举类型接口
export interface EnumArrayObj {
  value: number | string
  label: string //中文key,方便阅读
  displayText?: string //展示的文字,只有和label不同的时候使用,
}

export type ValueOf<T extends readonly EnumArrayObj[]> = T[number]['value']
export type LabelOf<T extends readonly EnumArrayObj[]> = T[number]['label']
export type ItemOf<T extends readonly EnumArrayObj[]> = {
  value: ValueOf<T>
  label: LabelOf<T>
  displayText?: string
}
/**
 * 枚举数组类,继承了Array
 */
export class EnumArray<
  T extends readonly EnumArrayObj[],
> extends Array<EnumArrayObj> {
  private readonly kvMap = new Map<string, ValueOf<T>>()
  private readonly vkMap = new Map<string, LabelOf<T>>()
  constructor(list: T) {
    super(list.length)
    for (let i = 0; i < list.length; i++) {
      const item = list[i]
      this[i] = item
      this.kvMap.set(item.label, item.value)
      this.vkMap.set(item.value + '', item.label)
    }
  }

  getLabelByValue(value: ValueOf<T>) {
    return this.vkMap.get(value + '')
  }

  getValueByLabel(label: LabelOf<T>) {
    return this.kvMap.get(label)
  }
  getItemByLabel(label: LabelOf<T>): ItemOf<T> | undefined {
    return this.find((item) => {
      return item.label === label
    })
  }
  getItemByValue(value: ValueOf<T>): ItemOf<T> | undefined {
    return this.find((item) => {
      return item.value === value
    })
  }
  getDisplayTextByLabel(label: LabelOf<T>) {
    const item = this.getItemByLabel(label)
    return item?.displayText ?? label
  }
  getDisplayTextByValue(value: ValueOf<T>) {
    const item = this.getItemByValue(value)
    return item?.displayText ?? item?.label
  }
}
export function createEnum<T extends readonly EnumArrayObj[]>(enums: T) {
  return Object.freeze(new EnumArray(enums))
}

使用的时候,比较方便,因为label的类型,用于状态判断还是挺常用了,所以也获取类型导出。。。

const sexList = [
  {
    label: '男',
    value: 1,
  },
  {
    label: '女',
    value: 2,
  },
] as const
export const sexEnum = createEnum(sexList)
export type sexLabel = LabelOf<typeof sexList>

相关文章

  • class 类

    基本用法 构造函数和this 继承 抽象类 接口(TypeScript 独有) 属性的封装 泛型

  • appium封装before和after遇到问题

    【问答】appium中使用testng测试,将before和after封装,测试类继承封装类,test报错 1.这...

  • Property 'fill' does not exist o

    在typescript中:new Array(9).fill('ab')但是tsc的时候报错:Property '...

  • C艹之路 1.1f继承与派生,多态与虚函数

    抽象,封装,继承,多态这是面向对象的四个特点抽象,封装指的类的声明继承指的是类的继承封装 封装 派生类 class...

  • 聊下枚举

    枚举定义: 一组具名的值的有限集合。 一、枚举的基本特性 当创建枚举类enum时,编译器会生成一个类,这个类继承与...

  • Swift3.0 基于AFN3.1.0简单封装

    今天只做一个最简单的网络封装。 类型枚举 建立一个工具类,应当继承自AFHTTPSessionManager Sw...

  • Java Enum的七种用法

    枚举 枚举是由class来实现的(继承Enum类,所以不能再继承其他类,也不能被继承,但是可用来实现接口)。因此由...

  • Swift5.0 - day5-继承、初始化、可选链、协议

    一、继承(Inheritance) 1.1、类继承值类型(枚举、结构体) 不支持继承,只有 类 支持继承;没有父类...

  • Enum枚举类的认识

    枚举类:默认继承java.lang.Enum类,不能再继承其他类,但是可以实现一个或多个接口。不是个抽象类。 枚举...

  • Swift枚举高级用法(Enum)

    关于swift的枚举 一 swift对于枚举的扩展性(Enum) 枚举的继承(继承任何类和协议,目前除了swift...

网友评论

      本文标题:typescript枚举类的封装,继承Array时报错Sprea

      本文链接:https://www.haomeiwen.com/subject/umzaedtx.html