react-elegant-ui
Version:
Elegant UI components, made by BEM best practices for react
104 lines (103 loc) • 3.95 kB
TypeScript
import { ComponentType, FC } from 'react';
export type FilterByKeys<T, F = any> = {
[K in keyof T as K extends F ? K : never]: T[K];
};
/**
* Interface of HOC options
*/
export interface HOCOptions<S extends {}> {
/**
* State to call HOC. Empty mean any
*
* When props is not match - will render default component
*/
matchProps?: Partial<S>;
/**
* Make private all props from option `matchProps`
*
* It alternative to manually specifying all props from `matchProps` to `privateProps`
*/
privateMatchProps?: boolean;
/**
* Array of all props names unique for this HOC
*
* Here should specify only props defined of HOC, but not common props!
*
* This props will removed when HOC is not match and other matched HOCs in compose unit
* is not specified it as `matchProps` or `privateProps`
*/
privateProps?: Exclude<keyof FilterByKeys<S, string>, symbol | number>[];
/**
* Array of props names that never be forward.
*
* Useful for props who will trigger match, but will not use in HOC
*/
matchOnlyProps?: Exclude<keyof FilterByKeys<S, string>, symbol | number>[];
}
/**
* Interface of HOC. It's function with property contains a HOC options
*/
export type ConfigurableHOC<HOCProps extends {}, OriginProps extends {} = {}> = {
<P extends {} = {}>(Component: ComponentType<P & HOCProps>): ComponentType<P & HOCProps & OriginProps>;
__hocOptions: HOCOptions<HOCProps>;
};
export type HOC<T> = (WrappedComponent: ComponentType) => ComponentType<T>;
/**
* Simply HOC for compose. It can be use instead `ConfigurableHOC`
*/
export type SimplyHOC<Props extends {}, Origin extends {} = {}> = <P extends {} = {}>(Component: ComponentType<P & Props>) => ComponentType<P & Props & Origin>;
/**
* Object for composer
*
* Fake version. It's just HOC. It use cuz TS is can't infer generic type from union `HOC | ConfigurableHOC`
* Real type name is `CompositeUnit`
*/
export type CompositeUnitSimple<T> = HOC<T>;
/**
* Object for composer
*/
export type CompositeUnit<T extends {}> = ConfigurableHOC<T> | HOC<T>;
/**
* Helper to extract props from `ComponentType`
*/
export type ExtractProps<T> = T extends ComponentType<infer K> ? {
[P in keyof K]: K[P];
} : never;
/**
* Result of composing
*
* This type also help infer types and show pretty props list instead generic names
* https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html#support-for-defaultprops-in-jsx
*/
export type Composition<T> = <U extends ComponentType<any>>(fn: U) => FC<JSX.LibraryManagedAttributes<U, ExtractProps<U>> & T>;
/**
* Useful to infer type from `CompositeUnitSimple`
*
* It may use with union types to apply for each naked type in union
*/
export type InferStructFromCompositeUnit<T> = T extends CompositeUnitSimple<infer X> ? X extends {} ? X : never : T;
/**
* Make intersection type from union type
*
* For more info see: https://fettblog.eu/typescript-union-to-intersection/
*
* @example
* // return `{foo: 1} & {bar: 2}`
* type intersection = UnionToIntersection<{foo: 1} | {bar: 2}>;
*/
export type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
type AllKeys<T> = T extends unknown ? keyof T : never;
type AddMissingProps<T, K extends PropertyKey = AllKeys<T>> = T extends unknown ? T & Record<Exclude<K, keyof T>, never> : never;
/**
* Object type which contain properties of all objects of union type, but values will intersections
*
* NOTE: it's not deep function, so objects properties on level 2 and higher will not changed
*
* @example
* // return `{foo?: 1 | 2 | undefined; bar: 3 | 8}`
* type intersection = ObjectsUnionToIntersection<{ foo: 1 } | { foo?: 2; bar: 3 } | { bar: 8 }>
*/
export type ObjectsUnionToIntersection<T> = {
[K in keyof AddMissingProps<T>]: AddMissingProps<T>[K];
};
export {};