Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Explicit returns on typescript functions #446

Merged
merged 5 commits into from
Feb 11, 2021
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion packages/react-components/.eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ module.exports = {
"no-param-reassign": "off",
"@typescript-eslint/no-explicit-any": "off",

"jsx-control-statements/jsx-jcs-no-undef": "off"
"jsx-control-statements/jsx-jcs-no-undef": "off",
"@typescript-eslint/explicit-function-return-type": ["warn", { allowExpressions: true }]
}
}
],
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export function resolvePopperPosition(upward: boolean, direction: "left" | "right") {
export function resolvePopperPosition(upward: boolean, direction: "left" | "right"): string {
return `${upward ? "top" : "bottom"}-${direction === "left" ? "end" : "start"}`;
}
2 changes: 1 addition & 1 deletion packages/react-components/src/shared/src/arrayify.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export function arrayify<T>(value: T | T[]) {
export function arrayify<T>(value: T | T[]): T[] {
return Array.isArray(value) ? value : [value];
}
4 changes: 2 additions & 2 deletions packages/react-components/src/shared/src/augmentElement.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ import { normalizeSize } from "./normalizeSize";
import React, { ElementType, HTMLAttributes, ReactElement, RefAttributes, cloneElement } from "react";
import type { SizeAdapter } from "./createSizeAdapter";

export function augmentElement(element: ReactElement & RefAttributes<any>, newProps: Record<string, any>) {
export function augmentElement(element: ReactElement & RefAttributes<any>, newProps: Record<string, any>): ReactElement {
const augmentedProps = mergeProps({ ...element.props, ref: element.ref }, newProps);

return cloneElement(element, augmentedProps);
}

export function createOrAugmentElement<T extends string, P extends HTMLAttributes<T>>(element: ReactElement<P, T> | ElementType, props: P) {
export function createOrAugmentElement<T extends string, P extends HTMLAttributes<T>>(element: ReactElement<P, T> | ElementType, props: P): ReactElement {
if (isValidElementType(element) && !isString(element)) {
const Type = element;

Expand Down
4 changes: 2 additions & 2 deletions packages/react-components/src/shared/src/createSizeAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ import type { Size } from "./size";

export type SizeAdapter = Record<Size, Size>;

export function createSizeAdapter(adapter: SizeAdapter) {
export function createSizeAdapter(adapter: SizeAdapter): (size: Size) => Size {
return (size: Size) => adapter[normalizeSize(size)];
}

export function adaptSize(size: Size, adapter: SizeAdapter) {
export function adaptSize(size: Size, adapter: SizeAdapter): Size {
return adapter[normalizeSize(size)];
}
2 changes: 1 addition & 1 deletion packages/react-components/src/shared/src/cssModule.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export function cssModule(moduleName: string, ...values: (false | string)[]) {
export function cssModule(moduleName: string, ...values: (false | string)[]): string {
const classes = values
.filter(Boolean)
.map(x => `${moduleName}-${x}`);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ interface FocusableTreeWalkerOptions {
tabbable?: boolean;
}

export function createFocusableTreeWalker(root: HTMLElement, { tabbable }: FocusableTreeWalkerOptions = {}) {
export function createFocusableTreeWalker(root: HTMLElement, { tabbable }: FocusableTreeWalkerOptions = {}): TreeWalker {
const selector = tabbable ? TabbableElementSelector : FocusableElementSelector;

const walker = document.createTreeWalker(
Expand All @@ -45,6 +45,6 @@ export function createFocusableTreeWalker(root: HTMLElement, { tabbable }: Focus
return walker;
}

export function walkFocusableElements(root: HTMLElement, onElement: (element: Element, index?: number) => void) {
export function walkFocusableElements(root: HTMLElement, onElement: (element: Element, index?: number) => void): void {
root.querySelectorAll(FocusableElementSelector).forEach((x, index) => onElement(x, index));
}
2 changes: 1 addition & 1 deletion packages/react-components/src/shared/src/mergeClasses.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export function mergeClasses(...values: (string | false)[]) {
export function mergeClasses(...values: (string | false)[]): string {
const deduped = (values
.filter(Boolean) as string[])
.reduce((set, x) => {
Expand Down
12 changes: 6 additions & 6 deletions packages/react-components/src/shared/src/mergeProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ interface CompositeKeyWeakMapNode<T> {
export class CompositeKeyWeakMap<T> {
_root = new WeakMap<any, any>();

set(keys: any[], value: T) {
set(keys: any[], value: T): void {
let node: WeakMap<any, any> | CompositeKeyWeakMapNode<T> = this._root;

for (let i = 0; i < keys.length; i += 1) {
Expand All @@ -35,7 +35,7 @@ export class CompositeKeyWeakMap<T> {
(node as CompositeKeyWeakMapNode<T>).value = value;
}

get(keys: any[]) {
get(keys: any[]): T {
let node: WeakMap<any, any> | CompositeKeyWeakMapNode<T> = this._root;

for (let i = 0; i < keys.length; i += 1) {
Expand All @@ -50,7 +50,7 @@ export class CompositeKeyWeakMap<T> {
return (node as CompositeKeyWeakMapNode<T>).value;
}

has(keys: any[]) {
has(keys: any[]): boolean {
return !isUndefined(this.get(keys));
}
}
Expand All @@ -59,7 +59,7 @@ export class CompositeKeyWeakMap<T> {

const cache = new CompositeKeyWeakMap<any>();

function memoMerge<TFirst, TSecond, TOutput>(x: TFirst, y: TSecond, fct: (y: TSecond, x: TFirst) => TOutput) {
function memoMerge<TFirst, TSecond, TOutput>(x: TFirst, y: TSecond, fct: (y: TSecond, x: TFirst) => TOutput): undefined | TFirst | TSecond | TOutput {
if (isNil(x) && isNil(y)) {
return undefined;
}
Expand All @@ -86,7 +86,7 @@ function memoMerge<TFirst, TSecond, TOutput>(x: TFirst, y: TSecond, fct: (y: TSe
return mergeResult;
}

function merge(props: any, newProps: any) {
function merge(props: any, newProps: any): any {
Object
.keys(newProps)
.forEach(x => {
Expand Down Expand Up @@ -117,7 +117,7 @@ function merge(props: any, newProps: any) {
type TupleTypes<T> = { [P in keyof T]: T[P] } extends { [key: number]: infer V } ? V : never;
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;

export function mergeProps<T extends Record<string, any>[]>(...args: T) {
export function mergeProps<T extends Record<string, any>[]>(...args: T): UnionToIntersection<TupleTypes<T>> {
let result = {};

args.forEach(x => {
Expand Down
2 changes: 1 addition & 1 deletion packages/react-components/src/shared/src/omitProps.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export function omitProps<TObject extends Record<string, any>, TKey extends keyof TObject>(obj: TObject, props: TKey[]) {
export function omitProps<TObject extends Record<string, any>, TKey extends keyof TObject>(obj: TObject, props: TKey[]): Omit<TObject, TKey> {
return Object.keys(obj)
.reduce((acc: Record<string, any>, x: string) => {
if (!props.includes(x as TKey)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Fragment, ReactElement, ReactNode } from "react";
import { isFunction, isNil } from "lodash";

// Support first level fragment: https://github.com/facebook/react/issues/11859.
export function resolveFragment(children: ReactNode) {
export function resolveFragment(children: ReactNode): ReactNode {
if (!isNil(children) && (children as ReactElement).type === Fragment) {
return (children as ReactElement).props.children;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { Ref } from "semantic-ui-react";
import { isNil } from "lodash";
import React, { Ref as InnerRef, ReactElement } from "react";
import React, { Ref as InnerRef, ReactElement, ReactNode } from "react";

interface SemanticRefProps {
innerRef: InnerRef<HTMLElement> | null
children: ReactElement
}

export function SemanticRef({ innerRef, children }: SemanticRefProps) {
export function SemanticRef({ innerRef, children }: SemanticRefProps): ReactNode {
if (!isNil(innerRef)) {
return (
<Ref innerRef={innerRef}>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { IS_PRODUCTION } from "../OLD_env";
import { isNil } from "lodash";

export function throwWhenUnsupportedPropIsProvided(props: Record<string, any>, unsupportedProps: string[], componentName: string) {
export function throwWhenUnsupportedPropIsProvided(props: Record<string, any>, unsupportedProps: string[], componentName: string): void {
if (!IS_PRODUCTION) {
unsupportedProps.forEach(x => {
if (!isNil(props[x])) {
Expand Down
6 changes: 3 additions & 3 deletions packages/react-components/src/shared/src/slots.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ interface SlottedElement {
[SLOT_KEY]?: string;
}

function slotDecorator<P>(slotName: string, ElementType: P) {
function slotDecorator<P>(slotName: string, ElementType: P): P {
(ElementType as Record<string, unknown>)[SLOT_KEY] = slotName;

return ElementType;
Expand All @@ -24,7 +24,7 @@ interface Slots {
[x: string]: any;
}

export function getSlots(children: ReactNode, { _ = {}, ...slots }: Slots) {
export function getSlots(children: ReactNode, { _ = {}, ...slots }: Slots): Record<string, unknown> {
const slotElements: Record<string, unknown> = {};

children = resolveChildren(children);
Expand Down Expand Up @@ -83,6 +83,6 @@ export function getSlots(children: ReactNode, { _ = {}, ...slots }: Slots) {
return slotElements;
}

export function useSlots(children: ReactElement, slots: Slots) {
export function useSlots(children: ReactElement, slots: Slots): Record<string, unknown> {
return useMemo(() => getSlots(children, slots), [children, slots]);
}
2 changes: 1 addition & 1 deletion packages/react-components/src/shared/src/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export const StyleContext = createContext<StyleContextProps>(undefined);

export const StyleProvider = StyleContext.Provider;

export function useStyleContext() {
export function useStyleContext(): StyleContextProps {
return useContext(StyleContext);
}

Expand Down
6 changes: 3 additions & 3 deletions packages/react-components/src/shared/src/useAutoFocus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ interface AutoFocusOptions extends FocusOptions {
delay?: number;
}

function useAbstractAutoFocus({ isDisabled, delay, onFocus }: AutoFocusOptions) {
function useAbstractAutoFocus({ isDisabled, delay, onFocus }: AutoFocusOptions): void {
useEffect(() => {
const d = disposables();

Expand All @@ -30,7 +30,7 @@ function useAbstractAutoFocus({ isDisabled, delay, onFocus }: AutoFocusOptions)
}, [isDisabled, delay, onFocus]);
}

export function useAutoFocus<T extends HTMLElement>(targetRef: MutableRefObject<T>, { isDisabled, delay, onFocus }: AutoFocusOptions = {}) {
export function useAutoFocus<T extends HTMLElement>(targetRef: MutableRefObject<T>, { isDisabled, delay, onFocus }: AutoFocusOptions = {}): void {
useAbstractAutoFocus({
isDisabled,
delay,
Expand All @@ -42,7 +42,7 @@ export function useAutoFocus<T extends HTMLElement>(targetRef: MutableRefObject<
});
}

export function useAutoFocusChild(focusManager: FocusManager, { target = FocusTarget.first, isDisabled, delay, canFocus, onFocus, onNotFound }: AutoFocusOptions = {}) {
export function useAutoFocusChild(focusManager: FocusManager, { target = FocusTarget.first, isDisabled, delay, canFocus, onFocus, onNotFound }: AutoFocusOptions = {}): void {
useAbstractAutoFocus({
isDisabled: isDisabled,
delay,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@ export function createChainedFunction<T extends ChainableFunction>(...funcs: (T
};
}

export function useChainedEventCallback<T extends ChainableFunction>(...callbacks: (T | false)[]) {
export function useChainedEventCallback<T extends ChainableFunction>(...callbacks: (T | false)[]): ChainableFunction {
return useEventCallback(createChainedFunction(...callbacks));
}
4 changes: 2 additions & 2 deletions packages/react-components/src/shared/src/useCommittedRef.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// Copied from https://github.com/react-restart/hooks/blob/master/src/useCommittedRef.ts.

import { useEffect, useRef } from "react";
import { MutableRefObject, useEffect, useRef } from "react";

export function useCommittedRef<T>(value: T) {
export function useCommittedRef<T>(value: T): MutableRefObject<T> {
const ref = useRef(value);

useEffect(() => {
Expand Down
19 changes: 13 additions & 6 deletions packages/react-components/src/shared/src/useControllableState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,29 @@ import { isFunction, isUndefined } from "lodash";
import { useCallback, useRef } from "react";
import { useRefState } from "./useRefState";

function validatePrerequisites(controlledValue: any, initialValue: any) {
function validatePrerequisites(controlledValue: any, initialValue: any): void {
if (!isUndefined(controlledValue) && !isUndefined(initialValue)) {
throw new Error(
"useControllableState - A controllable state value can either have a controlled value or an initial value, but not both."
);
}
}

function ensureControlledStateHaveNotChanged(controlledValue: any, isControlled: any) {
function ensureControlledStateHaveNotChanged(controlledValue: any, isControlled: any): void {
if ((isControlled && isUndefined(controlledValue)) || (!isControlled && !isUndefined(controlledValue))) {
throw new Error("useControllableState - A controllable state value cannot switch between controlled and uncontrolled. Did you inadvertently set a default value (defaultProps) for your controlled prop?");
}
}

function useComputeInitialState<T>(controlledValue: T, initialValue: T, defaultValue: T) {
const result = (state: T, isControlled: boolean, isInitialState = false) => ({ state, isControlled, isInitialState });

interface useComputeInitialStateResult<T> {
state: T;
isControlled: boolean;
isInitialState: boolean;
}

function useComputeInitialState<T>(controlledValue: T, initialValue: T, defaultValue: T): useComputeInitialStateResult<T> {
const result = (state: T, isControlled: boolean, isInitialState = false): useComputeInitialStateResult<T> => ({ state, isControlled, isInitialState });

const hasComputedRef = useRef(false);

Expand All @@ -42,7 +49,7 @@ function useComputeInitialState<T>(controlledValue: T, initialValue: T, defaultV
return result(state, isControlled, true);
}

function computeSubsequentState<T>(controlledValue: T, currentState: T, isControlled: boolean) {
function computeSubsequentState<T>(controlledValue: T, currentState: T, isControlled: boolean): { newState: T; hasChanged: boolean; } {
alexasselin008 marked this conversation as resolved.
Show resolved Hide resolved
let newState: T | null = null;
let hasChanged = false;

Expand Down Expand Up @@ -89,7 +96,7 @@ interface ControllableStateOptions<T> {
*
* setUncontrolledState("Neil Armstrong");
*/
export function useControllableState<T>(controlledValue: T, initialValue: T, defaultValue: T, { onChange }: ControllableStateOptions<T> = {}) {
export function useControllableState<T>(controlledValue: T, initialValue: T, defaultValue: T, { onChange }: ControllableStateOptions<T> = {}): [T, (maybeState: any) => void, boolean] {
validatePrerequisites(controlledValue, initialValue);

let { state: initialState, isControlled: isControlledProp, isInitialState } = useComputeInitialState(controlledValue, initialValue, defaultValue);
Expand Down
12 changes: 10 additions & 2 deletions packages/react-components/src/shared/src/useDisposables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,16 @@ import { useEffect, useState } from "react";
// eslint-disable-next-line @typescript-eslint/ban-types
type DisposableFunction = Function;

interface DisposableAPI {
requestAnimationFrame(callback: FrameRequestCallback): void;
nextFrame(callback: FrameRequestCallback): void;
setTimeout(callback: (...args: any[]) => void, ms: number, ...args: any[]): void;
add(callback: DisposableFunction): void;
dispose(): void;
}

// Took from https://github.com/tailwindlabs/headlessui/blob/develop/packages/%40headlessui-react/src/utils/disposables.ts
export function disposables() {
export function disposables(): DisposableAPI {
// eslint-disable-next-line no-shadow
const _disposables: DisposableFunction[] = [];

Expand Down Expand Up @@ -36,7 +44,7 @@ export function disposables() {
return api;
}

export function useDisposables() {
export function useDisposables(): DisposableAPI {
// Using useState instead of useRef so that we can use the initializer function.
const [d] = useState(disposables);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { isNil } from "lodash";
import { useCallback } from "react";
import { useCommittedRef } from "./useCommittedRef";

export function useEventCallback<T extends (...args: any[]) => void>(callback: T) {
export function useEventCallback<T extends (...args: any[]) => void>(callback: T): (...args: any[]) => void {
const ref = useCommittedRef(callback);

return useCallback((...args) => {
Expand Down
6 changes: 3 additions & 3 deletions packages/react-components/src/shared/src/useEventListener.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { isFunction, isNil } from "lodash";
import { useCallback, useEffect } from "react";

export function useEventListener(eventTarget: EventTarget | (() => EventTarget), eventName: string, listener: EventListenerOrEventListenerObject | null, active = true, capture = false) {
export function useEventListener(eventTarget: EventTarget | (() => EventTarget), eventName: string, listener: EventListenerOrEventListenerObject | null, active = true, capture = false): void {
useEffect(() => {
const target = isFunction(eventTarget) ? eventTarget() : eventTarget;

Expand All @@ -19,13 +19,13 @@ export function useEventListener(eventTarget: EventTarget | (() => EventTarget),
}, [eventTarget, eventName, listener, active, capture]);
}

export function useDocumentListener(eventName: string, listener: EventListenerOrEventListenerObject | null, active: boolean, capture: boolean) {
export function useDocumentListener(eventName: string, listener: EventListenerOrEventListenerObject | null, active: boolean, capture: boolean): void {
const documentTarget = useCallback(() => document, []);

useEventListener(documentTarget, eventName, listener, active, capture);
}

export function useWindowListener(eventName: string, listener: EventListenerOrEventListenerObject | null, active: boolean, capture: boolean) {
export function useWindowListener(eventName: string, listener: EventListenerOrEventListenerObject | null, active: boolean, capture: boolean): void {
const documentTarget = useCallback(() => window, []);

useEventListener(documentTarget, eventName, listener, active, capture);
Expand Down
Loading