@mxssfd/types
Version:
209 lines (168 loc) • 10.7 kB
TypeScript
/** 获取嵌套对象的全部子路径 */
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 { }