import { HttpParams } from '@angular/common/http'; import { Signal, WritableSignal } from '@angular/core'; import { Dayjs } from 'dayjs'; /** ====================== Helpers: unwrap & shape ====================== **/ type IsEmptyObject = [keyof Obj] extends [never] ? true : false; type UnwrapAllSignals = T extends Signal ? UnwrapAllSignals : T; type Clean = Exclude, undefined | null>; type StrKeys = Extract; /** ====================== Array helpers ====================== **/ type ArrayElementRaw = UnwrapAllSignals> extends ReadonlyArray ? U : UnwrapAllSignals> extends (infer U)[] ? U : never; type IsArrayLike = UnwrapAllSignals> extends readonly unknown[] ? true : UnwrapAllSignals> extends unknown[] ? true : false; type IsNonArrayObject = UnwrapAllSignals> extends object ? (UnwrapAllSignals> extends readonly unknown[] ? false : UnwrapAllSignals> extends unknown[] ? false : true) : false; /** ====================== DOM/Evt guard ====================== **/ type IsDOMType = UnwrapAllSignals extends Event | Node | Document | Element | Window | CSSStyleDeclaration | CSSRule | CSSStyleSheet ? true : false; /** ====================== Finalize (giữ Signal nếu cần) ====================== **/ type Finalize = R extends true ? T : UnwrapAllSignals; /** ====================== Depth limiter (hybrid, mặc định 6) ====================== **/ type Dec = N extends 6 ? 5 : N extends 5 ? 4 : N extends 4 ? 3 : N extends 3 ? 2 : N extends 2 ? 1 : N extends 1 ? 0 : 0; /** ====================== Path builders (Depth-limited) ====================== **/ type PathForArray = [Depth] extends [0] ? never : `[${number}]` | (PathOf, Dec> extends never ? never : `[${number}].${PathOf, Dec>}`); type PathForProp = [Depth] extends [0] ? K : IsArrayLike extends true ? `${K}` | `${K}[${number}]` | (PathOf, Dec> extends never ? never : `${K}[${number}].${PathOf, Dec>}`) : IsNonArrayObject extends true ? `${K}` | (PathOf, Dec> extends never ? never : `${K}.${PathOf, Dec>}`) : `${K}`; type PathForObject = { [K in StrKeys]: PathForProp; }[StrKeys]; /** ====================== Public: PathOf (hybrid, Depth mặc định 6) ====================== **/ export type PathOf = IsEmptyObject> extends true ? any : IsDOMType> extends true ? any : [Depth] extends [0] ? never : UnwrapAllSignals> extends readonly unknown[] | unknown[] ? PathForArray, Depth> : UnwrapAllSignals> extends object ? PathForObject>, Depth> : string; /** ====================== Resolve giá trị theo path ====================== **/ type GetInternal = TRaw extends null | undefined ? TRaw : P extends `[${infer I}].${infer Rest}` ? I extends `${number}` ? GetInternal, Rest, R> : any : P extends `[${infer I}]` ? I extends `${number}` ? Finalize, R> : any : P extends `${infer K}[${infer I}].${infer Rest}` ? K extends StrKeys>> ? I extends `${number}` ? GetInternal>[K]>, Rest, R> : any : any : P extends `${infer K}.${infer Rest}` ? K extends StrKeys>> ? IsArrayLike>[K]> extends true ? any : GetInternal>[K], Rest, R> : any : P extends `${infer K}[${infer I}]` ? K extends StrKeys>> ? I extends `${number}` ? Finalize>[K]>, R> : any : any : P extends `${infer K}` ? K extends StrKeys>> ? Finalize>[K], R> : any : any; /** ====================== Public: GetValueAtPath & GetReturnType ====================== **/ export type GetValueAtPath, R extends boolean = false> = TRaw extends null | undefined ? TRaw : GetInternal; export type GetReturnType, KS extends boolean, D extends GetValueAtPath | undefined> = D extends undefined ? GetValueAtPath : Exclude, null | undefined>; type IsSpecificType = [T] extends [ Event | Node | Document | Element | Window | CSSStyleDeclaration | CSSRule | CSSStyleSheet | HttpParams | Dayjs | Date | ((...args: any[]) => any) | Promise | Map | Set | WeakMap | WeakSet | RegExp | File | Blob | FileList | FormData ] ? true : false; type SignalOfNonNullable = [ T ] extends [WritableSignal] ? T : [IsSpecificType] extends [true] ? F extends true ? WritableSignal : T : [T] extends [ReadonlyArray] ? F extends true ? WritableSignal, P, true>>> : Array, P, true>> : [T] extends [object] ? F extends true ? WritableSignal<{ [K in keyof T]: SignalOfImpl; }> : { [K in keyof T]: SignalOfImpl; } : [T] extends [string | number | boolean] ? P extends true ? WritableSignal : T : WritableSignal; type SignalOfImpl = Extract extends never ? SignalOfNonNullable : SignalOfNonNullable, P, F> | Extract; export type SignalOf = SignalOfImpl; export type NonSignalOf = T extends null | undefined ? T : Clean extends Array ? Array>> : Clean extends object ? { [K in keyof Clean]: NonSignalOf[K]>>; } : Clean; /** ====================== (Tuỳ chọn) Ví dụ nhanh ====================== **/ export type T_PageBotConfig = { enabled: boolean; mode?: 'AUTO' | 'REVIEW'; }; export type T_Signal_PageBotConfig = SignalOf; export interface IComment { comments?: WritableSignal; } export interface ISubComment { store?: WritableSignal>>; data?: WritableSignal>>; specific_temp_data?: WritableSignal>>; paging?: WritableSignal<{ cursors?: WritableSignal<{ after?: WritableSignal; before?: WritableSignal; }>; before?: WritableSignal; after?: WritableSignal; next?: WritableSignal; previous?: WritableSignal; }>; summary?: WritableSignal<{ can_comment?: WritableSignal; canorder_comment?: WritableSignal; total_count?: WritableSignal; }>; } export interface Test { specific_query?: WritableSignal; data: WritableSignal>>; index: number; info: { name: string; age: number; animal: boolean; cate: 'alo' | 'alo2'; }; city: WritableSignal<{ name: string; country: string; }>; address: WritableSignal<{ ip: WritableSignal; port: WritableSignal; }>; owner: Array; support: Array>; host: Array<{ ip: WritableSignal; port: number; }>; country: WritableSignal; code: WritableSignal<{ vi: WritableSignal; en: WritableSignal; }>; flag: WritableSignal; phone_code: string; currency: { name: string; code: WritableSignal; symbol: WritableSignal<{ vi: string; en: string; cn: WritableSignal>; jp: WritableSignal>>; }>; }; }>>>; } interface IAssignmentItem { id: WritableSignal; name: WritableSignal; description: WritableSignal; created_at: WritableSignal; updated_at: WritableSignal; assignees?: WritableSignal>>; chatbot_config?: WritableSignal; } export interface IAssignee { assignee_id?: WritableSignal; conversation_id?: WritableSignal; created_time?: WritableSignal; created_user?: WritableSignal; id?: WritableSignal; note?: WritableSignal; status?: WritableSignal; assign_tag_activity_status?: WritableSignal; comment_id?: WritableSignal; rating_id?: WritableSignal; } export interface IAssignmentItemQuery { per_page: WritableSignal; after_token?: WritableSignal; before_token?: WritableSignal; search?: WritableSignal; search_index?: WritableSignal; } export {};