110 lines
3.3 KiB
TypeScript
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;
|
|
}
|