UNPKG

@etsoo/shared

Version:

TypeScript shared utilities and functions

479 lines (478 loc) 13.4 kB
/** * Generic object type * Narrow case, uses StringRecord * Before was wrong with {}, from 4.8 unknown = {} | null | undefined */ declare global { interface BigInt { toJSON(): String; } } /** * Interface data types */ export declare namespace DataTypes { /** * Basic types, includes number, bigint, Date, boolean, string */ type Basic = number | bigint | Date | boolean | string; /** * Basic type and basic type array names array */ const BasicArray: readonly ["number", "number[]", "bigint", "bigint[]", "date", "date[]", "boolean", "boolean[]", "string", "string[]", "unknown[]"]; /** * Basic type names */ type BasicNames = (typeof BasicArray)[number]; /** * Basic type template */ type BasicTemplate = { [key: string]: BasicNames; }; /** * Basic template type */ type BasicTemplateType<T extends BasicTemplate> = { [P in keyof T]?: BasicConditional<T[P]>; }; /** * Basic conditinal type */ type BasicConditional<T extends BasicNames> = T extends "string" ? string : T extends "string[]" ? string[] : T extends "date" ? Date : T extends "date[]" ? Date[] : T extends "boolean" ? boolean : T extends "boolean[]" ? boolean[] : T extends "number" ? number : T extends "number[]" ? number[] : T extends "bigint" ? bigint : T extends "bigint[]" ? bigint[] : unknown[]; /** * Basic or basic array type */ type Simple = Basic | Array<Basic>; /** * Simple type enum */ enum SimpleEnum { Number = 1, Bigint = 2, Date = 3, Boolean = 4, String = 5, Array = 9 } /** * Simple type names */ type SimpleNames = Lowercase<keyof typeof SimpleEnum>; /** * Extended type enum */ enum ExtendedEnum { Unkwown = 0, Int = 10, Money = 11, IntMoney = 12, DateTime = 13, Email = 21, Phone = 22, URL = 23, Logo = 24 } /** * Combined type enum */ const CombinedEnum: { [x: number]: string; Unkwown: ExtendedEnum.Unkwown; Int: ExtendedEnum.Int; Money: ExtendedEnum.Money; IntMoney: ExtendedEnum.IntMoney; DateTime: ExtendedEnum.DateTime; Email: ExtendedEnum.Email; Phone: ExtendedEnum.Phone; URL: ExtendedEnum.URL; Logo: ExtendedEnum.Logo; Number: SimpleEnum.Number; Bigint: SimpleEnum.Bigint; Date: SimpleEnum.Date; Boolean: SimpleEnum.Boolean; String: SimpleEnum.String; Array: SimpleEnum.Array; }; type CombinedEnum = SimpleEnum | ExtendedEnum; /** * Horizontal align enum */ enum HAlignEnum { Left = 1, Center = 2, Right = 3 } /** * Horizontal align */ type HAlign = Lowercase<keyof typeof HAlignEnum>; /** * Vertical align enum */ enum VAlignEnum { Top = 1, Center = 2, Bottom = 3 } /** * Vertical align */ type VAlign = Lowercase<keyof typeof VAlignEnum>; /** * Placement enum */ enum PlacementEnum { TopLeft = 0, TopCenter = 1, TopRight = 2, MiddleLeft = 3, Center = 4, MiddleRight = 5, BottomLeft = 6, BottomCenter = 7, BottomRight = 8, Unknown = 9 } /** * Placement type */ type Placement = keyof typeof PlacementEnum; /** * Edit type from adding type */ type EditType<T, I extends IdType = number> = Partial<T> & { id: I; changedFields?: (keyof T & string)[]; }; /** * Key collection, like { key1: {}, key2: {} } */ type KeyCollection<K extends readonly string[], I extends object> = { [P in K[number]]: I; }; /** * Enum value type */ type EnumValue = number | string; /** * Enum base type */ type EnumBase = Record<string, EnumValue>; /** * Function type */ type Func<R> = (...args: any[]) => R; /** * Mixins constructor */ type MConstructor<T = {}> = new (...args: any[]) => T; /** * Make properties optional */ type Optional<T, K extends keyof T> = Pick<Partial<T>, K> & Omit<T, K>; /** * String key, unknown value Record */ type StringRecord = Record<string, unknown>; /** * String key, string value Record */ type StringDictionary = Record<string, string>; /** * Simple object, string key, simple type and null value Record */ type SimpleObject = Record<string, Simple | null | undefined>; /** * Item with id property */ type IdItem<T extends IdType = number> = { /** * Id field */ id: T; }; /** * Item with id and label property */ type IdLabelItem<T extends IdType = number> = IdItem<T> & { /** * label field */ label: string; }; /** * Item with id and name property */ type IdNameItem<T extends IdType = number> = IdItem<T> & { /** * name field */ name: string; }; /** * Item with id and title property */ type IdTitleItem<T extends IdType = number> = IdItem<T> & { /** * title field */ title: string; }; /** * Item with id and label dynamic type */ type IdLabelType<I extends string, L extends string, D extends IdType = number> = DIS<I, D> & DIS<L, string>; /** * Get specific type keys */ type Keys<T extends object, R = IdType> = { [k in keyof T]: T[k] extends R ? k : never; }[keyof T]; /** * Require at least one property of the keys */ type RequireAtLeastOne<T, Keys extends keyof T> = Pick<T, Exclude<keyof T, Keys>> & { [K in Keys]-?: Required<Pick<T, K>> & Partial<Pick<T, Exclude<Keys, K>>>; }[Keys]; /** * Culture definiton */ type CultureDefinition<T extends StringRecord = StringRecord> = { /** * Name, like zh-CN */ readonly name: string; /** * Label for description, like Simplifined Chinese */ label: string; /** * Resources */ resources: T | (() => Promise<T>); /** * Compatible names */ readonly compatibleNames?: string[]; }; /** * Dynamic interface with multiple properties */ type DI<K extends readonly string[], T> = { [P in K[number]]: T; }; /** * Dynamic interface with single property */ type DIS<K extends string, T> = { [P in K]: T; }; /** * Tristate enum * 三态枚举 */ enum TristateEnum { /** * False * 假 */ False = 0, /** * True * 真 */ True = 1, /** * Unsure * 无法判断 */ Unsure = 9 } /** * Convert value to target type * @param input Input value * @param target Target type * @returns Converted value */ function convert<T>(input: unknown, target: T): T | undefined; /** * Convert by type name like 'string' * @param input Input value * @param targetType Target type * @returns Converted value */ function convertByType<T extends BasicNames>(input: unknown, targetType: T): BasicConditional<T> | undefined; /** * Convert value to target enum type * @param input Input value * @param enumType Target enum type * @returns Converted type */ function convertSimple(input: unknown, enumType: CombinedEnum): Simple | unknown[] | undefined; /** * Get basic type name from Enum type * @param enumType Enum type * @returns Basic type name result */ function getBasicName(enumType: CombinedEnum): BasicNames; /** * Get value's basic type name * @param value Input value * @param isArray Is array * @returns Value's basic type name */ function getBasicNameByValue(value: unknown, isArray?: boolean): BasicNames | undefined; /** * Get enum item from key * getEnumByKey(Gender, "Male") === Gender.Male * @param enumItem Enum * @param key Key * @returns Enum item */ function getEnumByKey<T extends EnumBase, K extends keyof T>(enumItem: T, key: string): T[K] | undefined; /** * Get enum item from value * getEnumByKey(Gender, "M") === Gender.Male * @param enumItem Enum * @param value Key * @returns Enum item or undefined */ function getEnumByValue<T extends EnumBase, K extends keyof T>(enumItem: T, value: EnumValue): T[K] | undefined; /** * Get enum string literal type value * getEnumKey(Gender, "F") === "Female" * @param enumItem Enum item * @param value Value * @returns Result */ function getEnumKey<T extends EnumBase>(enumItem: T, value: EnumValue): string | undefined; /** * Get Enum keys * @param input Input Enum * @returns Keys */ function getEnumKeys<T extends EnumBase, K extends keyof T & string>(input: T): K[]; /** * Get ListType2 item label * @param item Item * @returns Result */ function getListItemLabel<D extends ListType2>(item: D): string; /** * Get object item label * @param item Item * @returns Result */ function getObjectItemLabel(item: object): string; /** * Get object field value * @param data Data * @param key Property name * @returns Value */ function getValue<T extends object, K extends keyof T | string>(data: T | undefined | null, key: K): K extends keyof T ? T[K] : undefined; /** * Get object id field value * @param data Data * @param key Property name * @returns Id value */ function getIdValue<T extends object, K extends Keys<T, IdType>>(data: T, key: K): T[K]; /** * Get object id field value 1 * @param data Data * @param key Property name * @returns Id value */ function getIdValue1<T extends object, K extends keyof T | string>(data: T | undefined | null, key: K): K extends keyof T ? (T[K] extends number ? number : string) : undefined; /** * Get object string field value * @param data Data * @param key Property name * @returns String value */ function getStringValue<T extends object>(data: T | undefined | null, key: keyof T | string): string | undefined; /** * Check the type is a basic type or not (type guard) * @param name Type name * @returns Is basic type */ function isBasicName(name: string): name is BasicNames; /** * Is the target a simple object (Type guard) * @param input Test data * @param includeArray Include array as simple type * @returns Result */ function isSimpleObject(input: unknown, includeArray?: boolean): input is SimpleObject; /** * Is the input value simple type, include null and undefined * @param input Input value * @param includeArray Is array included, first non null element shoud also be basic type */ function isSimpleType(input: unknown, includeArray?: boolean): boolean; /** * JSON.stringify replacer with full path * https://stackoverflow.com/questions/61681176/json-stringify-replacer-how-to-get-full-path */ function jsonReplacer(replacer: (this: any, key: string, value: any, path: string) => any): (this: any, key: any, value: any) => any; /** * JSON.stringify receiver for bigint * @param args Keys or paths to convert to bigint * @returns JSON receiver function */ function jsonBigintReceiver(...args: string[]): (this: any, key: any, value: any) => any; /** * JSON serialize with options * @param obj Object to serialize * @param options Options to ignore null or empty values * @returns Result */ function jsonSerialize(obj: unknown, options?: { ignoreNull?: boolean; ignoreEmpty?: boolean; }): string; } /** * Number and string combination id type */ export type IdType = number | string; /** * List item with number id type */ export type ListType = DataTypes.IdLabelItem<number>; /** * List item with string id type */ export type ListType1 = DataTypes.IdLabelItem<string>; /** * List item with compatible id and name / label / title */ export type ListType2 = { id: IdType; } & ({ label: string; } | { name: string; } | { title: string; }); /** * Id default type */ export type IdDefaultType<T extends object, I extends IdType = IdType> = T extends { id: I; } ? DataTypes.Keys<T, I> & "id" : DataTypes.Keys<T, I>; /** * Label default type */ export type LabelDefaultType<T extends object> = T extends { label: string; } ? DataTypes.Keys<T, string> & "label" : DataTypes.Keys<T, string>; /** * Title default type */ export type TitleDefaultType<T extends object> = T extends { title: string; } ? DataTypes.Keys<T, string> & "title" : DataTypes.Keys<T, string>;