type ElementOf = T extends Array ? T[number] : never; type ValueOf = T[keyof T]; export type Concrete = { [Key in keyof T]-?: T[Key]; }; /** * If typeof `Value` is value, returns `Node`. * Otherwise returns the value. */ export type ValueAttribute = (() => Value) & ((value: Value) => Node); /** * If no params, returns `Value`. * Otherwise returns the `Node`. */ export type ObjectAttribute = (() => Value) & ( ? Value : never>(key: K | keyof K | boolean) => Node) & ( ? keyof Value : never, V extends Value extends Record ? ValueOf : never>(key: K, value: V | boolean) => Node); /** * If typeof `Value` is an array or an element of array, returns `Node`. * Otherwise returns the array. */ export type ArrayAttribute = (() => Value) & ((value: Value | ElementOf) => Node); /** * Filter Object keys with the specified prefix. * @example * type A = { 'mark.a': number, 'composition.b': number } * type B = FilterKey; // { 'a': number } */ export type FilterKey = T extends `${Prefix}.${infer Key}` ? Key : never; /** * Filter Object keys with `mark` as prefix. * @example * type A = { 'mark.a': number, 'composition.b': number } * type B = FilterKey; // { 'a': number } * @todo Remove component.xxxx */ export type FilterMark = T extends 'component.axisX' ? 'axisX' : T extends 'component.axisY' ? 'axisY' : T extends 'component.legends' ? 'legends' : FilterKey; /** * Filter Object keys with `composition` as prefix. * @example * type A = { 'mark.a': number, 'composition.b': number } * type B = FilterComposition; // { 'b': number } */ export type FilterComposition = FilterKey; /** * Map marks of library to Nodes. */ export type MarkOf, Node> = { [Key in keyof Library as FilterMark]: Node; }; /** * Map compositions of library to Nodes. */ export type CompositionOf, Node> = { [Key in keyof Library as FilterComposition]: Node; }; /** * Map descriptors to props of Nodes. */ export type PropsOf, Spec extends Record, Node> = { [Key in keyof Descriptor]: Descriptor[Key] extends { type: 'object'; } ? ObjectAttribute : Descriptor[Key] extends { type: 'value'; } ? ValueAttribute : ArrayAttribute; }; export {};