Skip to content

Commit

Permalink
Merge pull request #2299 from FormidableLabs/ts-migrate/utils
Browse files Browse the repository at this point in the history
TypeScript migration: more utils!
  • Loading branch information
scottrippey authored Jun 13, 2022
2 parents 6556fe5 + 891725c commit 4cdc95c
Show file tree
Hide file tree
Showing 24 changed files with 269 additions and 141 deletions.
27 changes: 16 additions & 11 deletions packages/victory-core/src/types/prop-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,24 @@ import {

export type StringOrNumberOrList = string | number | (string | number)[];

type Datum = any;

export interface AnimatePropTypeInterface {
duration?: number;
onEnd?: () => void;
onExit?: {
duration?: number;
before?: (datum: any) => AnimationStyle;
before?: (datum: Datum, index: number, data: Datum[]) => AnimationStyle;
};
onEnter?: {
duration?: number;
before?: (datum: any) => AnimationStyle;
after?: (datum: any) => AnimationStyle;
before?: (datum: Datum, index: number, data: Datum[]) => AnimationStyle;
after?: (datum: Datum, index: number, data: Datum[]) => AnimationStyle;
};
onLoad?: {
duration?: number;
before?: (datum: any) => AnimationStyle;
after?: (datum: any) => AnimationStyle;
before?: (datum: Datum, index: number, data: Datum[]) => AnimationStyle;
after?: (datum: Datum, index: number, data: Datum[]) => AnimationStyle;
};
easing?: AnimationEasing;
animationWhitelist?: string[];
Expand Down Expand Up @@ -77,15 +79,18 @@ export type DomainPaddingPropType =
export type RangeTuple = [number, number];
export type RangePropType = RangeTuple | { x?: RangeTuple; y?: RangeTuple };

type NumberValue = number | { valueOf(): number };
/**
* D3 scale function shape. Don't want to introduce typing dependency to d3
*/
export interface D3Scale {
(input: string | number): number;

domain: () => [number, number];
range: () => any;
copy: () => any;
export interface D3Scale<TRange = any> {
(input: NumberValue): number;

ticks: (count?: number) => number[];
tickFormat: (count?: number) => (d: number) => string;
domain: () => number[];
range: () => TRange[];
copy: () => this;
invert: (value: number) => number;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ export class VictoryContainer extends React.Component<VictoryContainerProps> {

const style = responsive
? this.props.style
: Helpers.omit(this.props.style, ["height", "width"]);
: Helpers.omit(this.props.style!, ["height", "width"]);

const userProps = UserProps.getSafeUserProps(this.props);

Expand Down
7 changes: 4 additions & 3 deletions packages/victory-core/src/victory-util/axis.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
import * as Collection from "./collection";
import * as Domain from "./domain";
import * as Helpers from "./helpers";
import { D3Scale } from "../types/prop-types";

/**
* Returns the axis (x or y) of a particular axis component
Expand Down Expand Up @@ -265,15 +266,15 @@ export function getTickFormat(props, scale) {
}
}

function downsampleTicks(ticks, tickCount) {
function downsampleTicks(ticks: number[], tickCount: number) {
if (!tickCount || !Array.isArray(ticks) || ticks.length <= tickCount) {
return ticks;
}
const k = Math.floor(ticks.length / tickCount);
return ticks.filter((d, i) => i % k === 0);
}

export function getTicks(props, scale, filterZero) {
export function getTicks(props, scale: D3Scale, filterZero = false) {
const { tickCount } = props;
const tickArray = getTickArray(props);
const tickValues = tickArray ? tickArray.map((v) => v.value) : undefined;
Expand Down Expand Up @@ -333,7 +334,7 @@ function getDomainFromData(props, axis) {
}

// exposed for use by VictoryChart
export function getDomain(props, axis) {
export function getDomain(props, axis?) {
const inherentAxis = getAxis(props);
if (axis && axis !== inherentAxis) {
return undefined;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,11 @@ export function downsample(data, maxPoints, startingIndex = 0) {
* @param {Array} expectedKeys: an array of expected data keys
* @returns {Array} the formatted data
*/
export function formatData(dataset, props, expectedKeys) {
export function formatData(
dataset: any[],
props: any,
expectedKeys?: string[]
) {
const isArrayOrIterable =
Array.isArray(dataset) || Immutable.isIterable(dataset);
if (!isArrayOrIterable || getLength(dataset) < 1) {
Expand Down Expand Up @@ -280,7 +284,7 @@ export function formatData(dataset, props, expectedKeys) {
// eslint-disable-line complexity
datum = parseDatum(datum);
const fallbackValues = { x: index, y: datum };
const processedValues = expectedKeys.reduce((memo, type) => {
const processedValues = expectedKeys!.reduce((memo, type) => {
const processedValue = accessor[type](datum);
const value =
processedValue !== undefined
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
export function continuousTransitions() {
import { AnimatePropTypeInterface } from "../types/prop-types";

export function continuousTransitions(): AnimatePropTypeInterface {
return {
onLoad: {
duration: 2000
Expand All @@ -12,7 +14,7 @@ export function continuousTransitions() {
};
}

export function continuousPolarTransitions() {
export function continuousPolarTransitions(): AnimatePropTypeInterface {
return {
onLoad: {
duration: 2000,
Expand Down Expand Up @@ -56,7 +58,7 @@ export function continuousPolarTransitions() {
};
}

export function discreteTransitions() {
export function discreteTransitions(): AnimatePropTypeInterface {
return {
onLoad: {
duration: 2000,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,12 @@ function getDomainPadding(props, axis) {
: formatPadding(props.domainPadding);
}

function getFlatData(dataset, axis) {
return flatten(dataset).map((datum) => {
return datum[`_${axis}`] && datum[`_${axis}`][1] !== undefined
? datum[`_${axis}`][1]
: datum[`_${axis}`];
function getFlatData(dataset, axis: "x" | "y") {
const axisKey = `_${axis}`;
return flatten(dataset).map((datum: any) => {
return datum[axisKey] && datum[axisKey][1] !== undefined
? datum[axisKey][1]
: datum[axisKey];
});
}

Expand All @@ -60,7 +61,7 @@ function getExtremeFromData(dataset, axis, type = "min") {
type === "max" ? Math.max(...arr) : Math.min(...arr);
const initialValue = type === "max" ? -Infinity : Infinity;
let containsDate = false;
const result = flatten(dataset).reduce((memo, datum) => {
const result = flatten(dataset).reduce((memo: number, datum: any) => {
const current0 =
datum[`_${axis}0`] !== undefined ? datum[`_${axis}0`] : datum[`_${axis}`];
const current1 =
Expand Down Expand Up @@ -128,7 +129,9 @@ function padDomain(domain, props, axis) {
if (addsQuadrants && singleQuadrantDomainPadding !== false) {
// Naive initial padding calculation
const initialPadding = {
// @ts-expect-error `max/min` might be dates
left: (Math.abs(max - min) * padding.left) / rangeExtent,
// @ts-expect-error `max/min` might be dates
right: (Math.abs(max - min) * padding.right) / rangeExtent
};

Expand Down Expand Up @@ -177,8 +180,8 @@ function padDomain(domain, props, axis) {
* @returns {Function} a function that takes props and axis and returns a formatted domain
*/
export function createDomainFunction(
getDomainFromDataFunction,
formatDomainFunction
getDomainFromDataFunction?,
formatDomainFunction?
) {
getDomainFromDataFunction = isFunction(getDomainFromDataFunction)
? getDomainFromDataFunction
Expand Down Expand Up @@ -227,7 +230,7 @@ export function getDomain(props, axis) {
* @param {Array} categories: an array of categories corresponding to a given axis
* @returns {Array|undefined} returns a domain from categories or undefined
*/
export function getDomainFromCategories(props, axis, categories) {
export function getDomainFromCategories(props, axis, categories?) {
categories = categories || Data.getCategories(props, axis);
const { polar, startAngle = 0, endAngle = 360 } = props;
if (!categories) {
Expand Down Expand Up @@ -428,7 +431,7 @@ export function getMinFromProps(props, axis) {
* for a given dimension i.e. only x values.
* @returns {Array} the symmetric domain
*/
export function getSymmetricDomain(domain, values) {
export function getSymmetricDomain(domain, values: number[]) {
const processedData = sortedUniq(values.sort((a, b) => a - b));
const step = processedData[1] - processedData[0];
return [domain[0], domain[1] + step];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,19 @@ function getPolarRange(props, axis) {

/**
* creates an object with some keys excluded
* replacement for lodash.omit for performance. does not mimick the entire lodash.omit api
* replacement for lodash.omit for performance. does not mimic the entire lodash.omit api
* @param {Object} originalObject: created object will be based on this object
* @param {Array<String>} ks: an array of keys to omit from the new object
* @returns {Object} new object with same properties as originalObject
*/
export function omit(originalObject, ks = []) {
export function omit<T, Keys extends keyof T>(
originalObject: T,
ks: Array<Keys> = []
): Omit<T, Keys> {
// code based on babel's _objectWithoutProperties
const newObject = {};
const newObject = {} as T;
for (const key in originalObject) {
// @ts-expect-error String is not assignable to Key
if (ks.indexOf(key) >= 0) {
continue;
}
Expand Down Expand Up @@ -189,7 +193,7 @@ export function createAccessor(key) {
return property(key);
}

export function modifyProps(props, fallbackProps, role) {
export function modifyProps(props, fallbackProps?, role?) {
const theme = props.theme && props.theme[role] ? props.theme[role] : {};
const themeProps = omit(theme, ["style"]);
const horizontal = isHorizontal(props);
Expand Down Expand Up @@ -218,13 +222,24 @@ export function getCurrentAxis(axis, horizontal) {
* @returns {Array} returns an array of results from calling the iteratee on all nested children
*/
/* eslint-disable max-params */
export function reduceChildren(
children,
iteratee,
export function reduceChildren<
TChildren extends React.ReactNode,
TItem,
TResult = TItem[]
>(
children: TChildren[],
iteratee: (
child: TChildren,
childName: string,
parent?: TChildren
) => TItem | null,
parentProps = {},
initialMemo = [],
combine = (memo, item) => memo.concat(item)
) {
// @ts-expect-error These defaults are hard to type
initialMemo: TResult = [],
combine: (memo: TResult, item: TItem) => TResult = (memo, item) =>
// @ts-expect-error These defaults are hard to type
memo.concat(item)
): TResult {
const sharedProps = [
"data",
"domain",
Expand All @@ -236,7 +251,7 @@ export function reduceChildren(
"maxDomain",
"horizontal"
];
const traverseChildren = (childArray, names, parent) => {
const traverseChildren = (childArray, names, parent?) => {
return childArray.reduce((memo, child, index) => {
const childRole = child.type && child.type.role;
const childName = child.props.name || `${childRole}-${names[index]}`;
Expand All @@ -252,7 +267,11 @@ export function reduceChildren(
child.type.role === "stack" &&
isFunction(child.type.getChildren)
? child.type.getChildren(childProps)
: React.Children.toArray(child.props.children).map((c) => {
: (
React.Children.toArray(
child.props.children
) as Array<React.ReactElement>
).map((c) => {
const nestedChildProps = assign(
{},
c.props,
Expand Down Expand Up @@ -284,7 +303,7 @@ export function reduceChildren(
/**
* @param {Object} props: the props object
* @returns {Boolean} returns true if the props object contains `horizontal: true` of if any
* children or nested children are hoizontal
* children or nested children are horizontal
*/
export function isHorizontal(props) {
if (props.horizontal !== undefined || !props.children) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,37 +1,41 @@
import type { Iterable, Record, List, Map } from "immutable";

export const IMMUTABLE_ITERABLE = "@@__IMMUTABLE_ITERABLE__@@";
export const IMMUTABLE_RECORD = "@@__IMMUTABLE_RECORD__@@";
export const IMMUTABLE_LIST = "@@__IMMUTABLE_LIST__@@";
export const IMMUTABLE_MAP = "@@__IMMUTABLE_MAP__@@";

export function isIterable(x) {
export function isIterable(x): x is Iterable<unknown, unknown> {
return !!(x && x[IMMUTABLE_ITERABLE]);
}

export function isRecord(x) {
export function isRecord(x): x is Record<string, unknown> {
return !!(x && x[IMMUTABLE_RECORD]);
}

export function isImmutable(x) {
export function isImmutable(
x
): x is Iterable<unknown, unknown> | Record<string, unknown> {
return isIterable(x) || isRecord(x);
}

export function isList(x) {
export function isList(x): x is List<unknown> {
return !!(x && x[IMMUTABLE_LIST]);
}

export function isMap(x) {
export function isMap(x): x is Map<unknown, unknown> {
return !!(x && x[IMMUTABLE_MAP]);
}

export function shallowToJS(x, whitelist) {
export function shallowToJS(x, whitelist?: Record<string, boolean | unknown>) {
return isIterable(x)
? x.reduce(
(prev, curr, key) => {
(result: any, curr: any, key: any) => {
if (whitelist && whitelist[key]) {
curr = shallowToJS(curr);
}
prev[key] = curr;
return prev;
result[key] = curr;
return result;
},
isList(x) ? [] : {}
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ export function getPolarVerticalAnchor(props, degrees) {
return orientation === "top" ? "end" : "start";
}

export function getPolarAngle(props, baseAngle) {
export function getPolarAngle(props, baseAngle?) {
const { labelPlacement, datum } = props;
if (!labelPlacement || labelPlacement === "vertical") {
return 0;
Expand Down
Loading

0 comments on commit 4cdc95c

Please sign in to comment.