UNPKG

@mxssfd/types

Version:
209 lines (168 loc) 10.7 kB
/** 获取嵌套对象的全部子路径 */ declare type AllPathsOf<NestedObj> = object extends NestedObj ? never : FlattenPathTuples<RecursivelyTuplePaths<NestedObj>>; export declare type BracketsToEmpty<T> = T extends `[]${infer U}` ? BracketsToEmpty<U> : T; /** * 排查最多5个最少2个Object中是否有重复的key name,有就返回重复的key name集合,否则返回合并之后的Object * @tips 多个object key重复时不一定会全部显示重复的key name出来,可能会去掉一个重复的key才会出现下一个重复的 * @example * CheckDuplicateKey<{ a: 1 }, { b: 2, e: 5 }, { c: 3 }, { d: 4 }, { e: 5, c: 3, d: 4 }> // 'e' | 'c' | 'd' */ export declare type CheckDuplicateKey<A, B = {}, C = {}, D = {}, E = {}> = CheckDuplicateKey5<A, B, C, D, E>; /** * 排查两个Object中是否有重复的key name,有就返回重复的key name集合,否则返回合并之后的Object * @example * CheckDuplicateKey2<{a:string},{b:string}>; // A & B * CheckDuplicateKey2<{a:string},{a:string}>; // never */ declare type CheckDuplicateKey2<A, B> = DuplicateKeys<A, B> extends never ? A & B : DuplicateKeys<A, B>; declare type CheckDuplicateKey3<A, B, C> = CheckDuplicateKey2<A, B> extends A & B ? CheckDuplicateKey2<C, CheckDuplicateKey2<A, B>> : CheckDuplicateKey2<A, B>; declare type CheckDuplicateKey4<A, B, C, D> = CheckDuplicateKey3<A, B, C> extends A & B & C ? CheckDuplicateKey2<D, CheckDuplicateKey3<A, B, C>> : CheckDuplicateKey3<A, B, C>; declare type CheckDuplicateKey5<A, B, C, D, E> = CheckDuplicateKey4<A, B, C, D> extends A & B & C & D ? CheckDuplicateKey2<E, CheckDuplicateKey4<A, B, C, D>> : CheckDuplicateKey4<A, B, C, D>; export declare type DotTrim<T> = T extends `${infer U}.` | `.${infer U}` ? DotTrim<U> : T; /** * 获取两个Object中重复的key name * @example * DuplicateKeys<{a:string}, {b:string}>; // never * DuplicateKeys<{a:string}, {a:string}>; // "a" * DuplicateKeys<{a:string;b:string}, {a:string}>; // "a" * DuplicateKeys<{a:string;b:string}, {a:string;b:string}>; // "a"|"b" */ export declare type DuplicateKeys<A, B> = { [P in keyof A]-?: P extends keyof B ? P : never; }[keyof A]; export declare type EmptyNotDef<T, D> = T extends '' ? T : D; export declare type ExcludeOptionalProps<T> = Pick<T, RequiredKeys<T>>; /** * Flatten tuples created by RecursivelyTupleKeys into a union of paths, like: * `['name'] | ['name', 'first' ] -> 'name' | 'name.first'` */ declare type FlattenPathTuples<PathTuple extends unknown[]> = PathTuple extends [] ? never : PathTuple extends [infer SinglePath] ? SinglePath extends string | number ? `${SinglePath}` : never : PathTuple extends [infer PrefixPath, ...infer RestTuple] ? PrefixPath extends string | number ? `${PrefixPath}.${FlattenPathTuples<Extract<RestTuple, (string | number)[]>>}` : never : string; export declare type IfEquals<X, Y, A = X, B = never> = (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y ? 1 : 2 ? A : B; export declare type Join<T extends string[], U extends string | number> = T[0] extends void ? '' : PickRest<T>['length'] extends 0 ? T[0] : `${T[0]}${U}${Join<PickRest<T>, U>}`; /** * 从函数参数中移除第一个参数类型 * @example * type p = OmitFirstParameters<(a:number, b:string)=>any>; // [b:string] */ export declare type OmitFirstParameters<T> = T extends (_: any, ...args: infer I) => any ? I : never; declare type OneLevelPathOf<T> = keyof T & (string | number); export declare type OptionalKeys<T> = { [K in keyof T]-?: {} extends { [P in K]: T[K]; } ? K : never; }[keyof T]; declare type PathForHint<T> = OneLevelPathOf<T>; export declare type PathOf<T, K extends string, P extends string = ''> = K extends `${infer U}.${infer V}` ? U extends keyof T ? PathOf<T[U], V, `${P}${U}.`> : T extends unknown[] ? PathOf<T[number], V, `${P}${number}.`> : `${P}${PathForHint<T>}` : K extends keyof T ? `${P}${K}` : T extends unknown[] ? `${P}${number}` : `${P}${PathForHint<T>}`; declare type PickRest<T extends any[] = any[]> = T extends [any?, ...infer U] ? U : never; export declare type PublicOnly<T> = Pick<T, keyof T>; export declare type ReadonlyKeys<T> = { [P in keyof T]-?: IfEquals<{ [Q in P]: T[P]; }, { -readonly [Q in P]: T[P]; }, never, P>; }[keyof T]; /** * Recursively convert objects to tuples, like * `{ name: { first: string } }` -> `['name'] | ['name', 'first']` */ declare type RecursivelyTuplePaths<NestedObj> = NestedObj extends (infer ItemValue)[] ? // Array 情况需要返回一个 number,然后继续递归 [ number ] | [number, ...RecursivelyTuplePaths<ItemValue>] : NestedObj extends Record<string, any> ? [keyof NestedObj] | { [Key in keyof NestedObj]: [Key, ...RecursivelyTuplePaths<NestedObj[Key]>]; }[Extract<keyof NestedObj, string>] : [ ]; export declare type RemoveStrStart<S extends string, START extends string> = S extends `${START}${infer U}` ? U : S; export declare type RequiredKeys<T> = { [K in keyof T]-?: {} extends { [P in K]: T[K]; } ? never : K; }[keyof T]; export declare type SettableProps<R extends HTMLElement> = { style?: SettableStyle; } & Partial<Omit<R, 'style' | ReadonlyKeys<R>>>; export declare type SettableStyle = Partial<Omit<CSSStyleDeclaration, ReadonlyKeys<CSSStyleDeclaration>>>; /** * 从元组中移除第一个item的类型 * @example * type t = ShiftTuple<[number, string]> // [string] */ export declare type ShiftTuple<T> = T extends [unknown, ...infer Rest] ? Rest : never; export declare type SplitTemplateStringTypeToTuple<T> = T extends `${infer First}.${infer Rest}` ? First extends `${number}` ? [number, ...SplitTemplateStringTypeToTuple<Rest>] : [First, ...SplitTemplateStringTypeToTuple<Rest>] : T extends `${number}` ? [number] : [T]; /** * 字符串模板 * @example * type S1 = StrTemplate<'1%s3', ['2']>; // 123 * type S2 = StrTemplate<'%s23', ['1']>; // 123 * type S3 = StrTemplate<'123', ['1']>; // 123 * type SW = StrTemplate<'a%sc%se', ['b', 'd']>; // abcde * type SW2 = StrTemplate<'a%sc%se', ['b', 'd', 'f']>; // abcde * type S5 = StrTemplate<'hell%s worl%s'> // hell worl */ export declare type StrTemplate<T extends string, S extends any[] = []> = T extends `${infer L}%s${infer R}` ? S['length'] extends 0 ? StrTemplate<`${L}${R}`> : StrTemplate<`${L}${S[0]}${R}`, ShiftTuple<S>> : T; /** * 字符串转换为小驼峰 * @example * * type t = ToCamelCase<'string-string-string', '-'>; // stringStringString * type t2 = ToCamelCase<'string_string-String', '_'>; // stringString-string * type t3 = ToCamelCase<'string_string-String'>; // stringString-string */ export declare type ToCamelCase<S extends string, D extends string = '_'> = S extends `${infer F}${D}${infer Rest}` ? `${Lowercase<F>}${Capitalize<ToCamelCase<Rest, D>>}` : Lowercase<S>; /** * 参考该文章改的路径转换type * @example * type fp = TransferPath<`[a]`>; // a * type fp1 = TransferPath<`[a][b][c]`>; // a.b.c * type fp2 = TransferPath<`a.b.c`>; // a.b.c * type fp3 = TransferPath<`a[b]`>; // a.b * type fp4 = TransferPath<`a.[b]`>; // a.b * type fp5 = TransferPath<`[a][b][c`>; // error a.b.[c * type fp6 = TransferPath<`a[b][c]`>; // a.b.c * type fp7 = TransferPath<`a[b]c`>; // a.b.c * type fp8 = TransferPath<`a[b].c`>; // a.b.c * type fp9 = TransferPath<`[a][b]c`>; // a.b.c */ export declare type TransferPath<P extends string, Path = DotTrim<P>> = Path extends `[${infer K}]${infer NextK}` ? NextK extends '' ? `${K}` : `${K}${EmptyNotDef<NextK, `.${TransferPath<NextK>}`>}` : Path extends `${infer K}[${infer NextK}]${infer Other}` ? `${K}${EmptyNotDef<NextK, `.${NextK}`>}${EmptyNotDef<BracketsToEmpty<Other>, `.${TransferPath<Other>}`>}` : Path extends `${infer K}.${infer NextK}` ? `${K}.${TransferPath<NextK>}` : Path; /** * 如果转换后的路径跟PathOf的路径一样,就说明该路径是对的并返回原path,否则返回PathOf所返回的类型 */ export declare type TransferPathOf<T extends object, K extends string, S extends string, NO_START extends string = DotTrim<RemoveStrStart<K, S>>, NO_START_PATH = TransferPath<NO_START>, PATH = PathOf<T, TransferPath<NO_START>>> = NO_START_PATH extends PATH ? K : PATH; /** * 返回一个由单一类型组成的元组 * * 注意:N最多为999,多了会报错 * * @example * type T = Tuple<number, 3> // => [number, number, number] * type T2 = Tuple<string, 2> // => [string, string] */ export declare type Tuple<T, N extends number, R extends unknown[] = []> = R['length'] extends N ? R : Tuple<T, N, [T, ...R]>; /** * 返回length为M到N的联合数组类型 * * @example * type a = TupleM2N<number, 0, 2>;// [] | [number] | [number, number] */ export declare type TupleM2N<T, M extends number, N extends number, I extends T[] = Tuple<T, M>, R extends unknown[] = []> = I['length'] extends N ? TupleToUnion<[...R, I]> : TupleM2N<T, M, N, [...I, T], [...R, I]>; /** * 把元组转成联合类型 * @example * type ttu = TupleToUnion<[number, string]>; // string | number */ export declare type TupleToUnion<T extends unknown[]> = T extends [infer F, ...infer REST] ? F | TupleToUnion<REST> : never; export declare type TypeOfPath<T, K extends string> = K extends `${infer A}.${infer B}` ? A extends keyof T ? TypeOfPath<T[A], B> : T extends Array<infer I> ? TypeOfPath<I, B> : never : K extends keyof T ? T[K] : T extends Array<infer I> ? I : never; export declare type UrlParams<T, R = {}> = T extends `${infer K}=${infer V}${infer Other}` ? UrlParams<Other extends `&${infer O}` ? O : Other, { [k in K]: V; }> & R : R; /** 给定子路径和嵌套对象,获取子路径对应的 value 类型 */ export declare type ValueMatchingPath<NestedObj, Path extends AllPathsOf<NestedObj>> = string extends Path ? any : object extends NestedObj ? any : NestedObj extends readonly (infer SingleValue)[] ? Path extends `${string}.${infer NextPath}` ? NextPath extends AllPathsOf<NestedObj[number]> ? ValueMatchingPath<NestedObj[number], NextPath> : never : SingleValue : Path extends keyof NestedObj ? NestedObj[Path] : Path extends `${infer Key}.${infer NextPath}` ? Key extends keyof NestedObj ? NextPath extends AllPathsOf<NestedObj[Key]> ? ValueMatchingPath<NestedObj[Key], NextPath> : never : never : never; export declare type WritableKeys<T> = { [P in keyof T]-?: IfEquals<{ [Q in P]: T[P]; }, { -readonly [Q in P]: T[P]; }, P>; }[keyof T]; export { }