mentalHealth/01-Web/packages/utils/common/objects.ts

110 lines
3.3 KiB
TypeScript

import { z } from 'zod';
/**
* 返回对象的可枚举属性和方法的名称
* - `Object.keys` 始终返回 `string[]` 类型,此函数可以返回具体类型
*
* @param {O} object 对象
* @returns {(keyof O)[]} 对象所有可枚举的属性的键名
*/
export function ObjectKeys<O extends Recordable>(object: O): (keyof O)[] {
return Object.keys(object);
}
/**
* 返回对象的可枚举属性的值数组
*
* @param {O} object 对象
*/
export function ObjectValues<O extends Recordable>(object: O): O[keyof O][] {
return Object.values(object) as O[keyof O][];
}
/**
* 返回对象的可枚举属性的键/值数组
* - 与 `ObjectEntriesRecord` 方法仅返回类型具体程度的区别
*
* @param {O} object 对象
*/
export function ObjectEntries<O extends Recordable>(object: O) {
return Object.entries(object) as [keyof O, O[keyof O]][];
}
/**
* 返回对象的可枚举属性的键/值数组
* - 与 `ObjectEntries` 方法仅返回类型具体程度的区别
*
* @param {{ [K in keyof O]: O[K] }} object 对象
*/
export function ObjectEntriesRecord<O extends Recordable<keyof O>>(object: { [K in keyof O]: O[K] }) {
return Object.entries(object) as [keyof O, O[keyof O]][];
}
/**
* 返回交换了对象的可枚举属性的值/键对象
*
* @param {O} object 对象
*/
export function ObjectSwitch<O extends Recordable<keyof O, string | number>>(object: Required<O>) {
const result = {} as unknown as Recordable<O[keyof O], keyof O>;
for (const [k, v] of EnumEntries(object)) {
result[v] = k;
}
return result;
}
/**
* 获取枚举所有属性的键
*
* @param {E} enums 枚举
*/
export function EnumKeys<E extends Recordable<keyof E>>(enums: E): [keyof E, ...(keyof E)[]] {
const e = z.record(z.unknown()).parse(enums) as E;
const keys = z
.array(z.string())
.nonempty({ message: 'Enum Keys must contain at least 1 element(s)' })
.parse(ObjectKeys(e)) as [keyof E, ...(keyof E)[]];
const values = ObjectValues(e);
const isNumEnum = keys.every((k) => values.some((v) => `${v}` === k));
if (isNumEnum) return keys.splice(keys.length / 2, keys.length / 2) as [keyof E, ...(keyof E)[]];
return keys;
}
/**
* 获取枚举所有属性的值
*
* @param {E} enums 枚举
*/
export function EnumValues<E extends Recordable<keyof E>>(enums: E): E[keyof E][] {
const e = z.record(z.unknown()).parse(enums) as E;
const keys = z
.array(z.string())
.nonempty({ message: 'Enum Keys must contain at least 1 element(s)' })
.parse(ObjectKeys(e));
const values = ObjectValues(e);
const isNumEnum = keys.every((k) => values.some((v) => `${v}` === k));
if (isNumEnum) return values.splice(keys.length / 2, keys.length / 2);
return values;
}
/**
* 返回枚举的属性的键/值数组
*
* @param {E} enums 枚举
*/
export function EnumEntries<E extends Recordable<keyof E>>(enums: E): [keyof E, E[keyof E]][] {
const e = z.record(z.unknown()).parse(enums) as E;
const keys = z
.array(z.string())
.nonempty({ message: 'Enum Keys must contain at least 1 element(s)' })
.parse(ObjectKeys(e));
const values = ObjectValues(e);
const entries = ObjectEntries(e);
const isNumEnum = keys.every((k) => values.some((v) => `${v}` === k));
if (isNumEnum) return entries.splice(keys.length / 2, keys.length / 2);
return entries;
}