mirror of
https://github.com/gosticks/DefinitelyTyped.git
synced 2025-10-16 12:05:41 +00:00
Merge pull request #33220 from Jessidhia/useref-undefined-overload
[react] Add some support for special cases using undefined with hooks
This commit is contained in:
commit
9e673d252d
25
types/react/index.d.ts
vendored
25
types/react/index.d.ts
vendored
@ -807,6 +807,14 @@ declare namespace React {
|
||||
* @see https://reactjs.org/docs/hooks-reference.html#usestate
|
||||
*/
|
||||
function useState<S>(initialState: S | (() => S)): [S, Dispatch<SetStateAction<S>>];
|
||||
// convenience overload when first argument is ommitted
|
||||
/**
|
||||
* Returns a stateful value, and a function to update it.
|
||||
*
|
||||
* @version 16.8.0
|
||||
* @see https://reactjs.org/docs/hooks-reference.html#usestate
|
||||
*/
|
||||
function useState<S = undefined>(): [S | undefined, Dispatch<SetStateAction<S | undefined>>];
|
||||
/**
|
||||
* An alternative to `useState`.
|
||||
*
|
||||
@ -894,6 +902,20 @@ declare namespace React {
|
||||
*/
|
||||
// TODO (TypeScript 3.0): <T extends unknown>
|
||||
function useRef<T>(initialValue: T|null): RefObject<T>;
|
||||
// convenience overload for potentially undefined initialValue / call with 0 arguments
|
||||
// has a default to stop it from defaulting to {} instead
|
||||
/**
|
||||
* `useRef` returns a mutable ref object whose `.current` property is initialized to the passed argument
|
||||
* (`initialValue`). The returned object will persist for the full lifetime of the component.
|
||||
*
|
||||
* Note that `useRef()` is useful for more than the `ref` attribute. It’s handy for keeping any mutable
|
||||
* value around similar to how you’d use instance fields in classes.
|
||||
*
|
||||
* @version 16.8.0
|
||||
* @see https://reactjs.org/docs/hooks-reference.html#useref
|
||||
*/
|
||||
// TODO (TypeScript 3.0): <T extends unknown>
|
||||
function useRef<T = undefined>(): MutableRefObject<T | undefined>;
|
||||
/**
|
||||
* The signature is identical to `useEffect`, but it fires synchronously after all DOM mutations.
|
||||
* Use this to read layout from the DOM and synchronously re-render. Updates scheduled inside
|
||||
@ -958,7 +980,8 @@ declare namespace React {
|
||||
* @version 16.8.0
|
||||
* @see https://reactjs.org/docs/hooks-reference.html#usememo
|
||||
*/
|
||||
function useMemo<T>(factory: () => T, deps: DependencyList): T;
|
||||
// allow undefined, but don't make it optional as that is very likely a mistake
|
||||
function useMemo<T>(factory: () => T, deps: DependencyList | undefined): T;
|
||||
/**
|
||||
* `useDebugValue` can be used to display a label for custom hooks in React DevTools.
|
||||
*
|
||||
|
||||
@ -100,9 +100,46 @@ function useEveryHook(ref: React.Ref<{ id: number }>|undefined): () => boolean {
|
||||
// inline object, to (manually) check if autocomplete works
|
||||
React.useReducer(reducer, { age: 42, name: 'The Answer' });
|
||||
|
||||
// make sure this is not going to the |null overload
|
||||
// $ExpectType MutableRefObject<boolean>
|
||||
const didLayout = React.useRef(false);
|
||||
// test useRef and its convenience overloads
|
||||
// $ExpectType MutableRefObject<number>
|
||||
React.useRef(0);
|
||||
|
||||
// these are not very useful (can't assign anything else to .current)
|
||||
// but it's the only safe way to resolve them
|
||||
// $ExpectType MutableRefObject<null>
|
||||
React.useRef(null);
|
||||
// $ExpectType MutableRefObject<undefined>
|
||||
React.useRef(undefined);
|
||||
|
||||
// |null convenience overload
|
||||
// it should _not_ be mutable if the generic argument doesn't include null
|
||||
// $ExpectType RefObject<number>
|
||||
React.useRef<number>(null);
|
||||
// but it should be mutable if it does (i.e. is not the convenience overload)
|
||||
// $ExpectType MutableRefObject<number | null>
|
||||
React.useRef<number | null>(null);
|
||||
|
||||
// |undefined convenience overload
|
||||
// with no contextual type or generic argument it should default to undefined only (not {} or unknown!)
|
||||
// $ExpectType MutableRefObject<undefined>
|
||||
React.useRef();
|
||||
// $ExpectType MutableRefObject<number | undefined>
|
||||
React.useRef<number>();
|
||||
// don't just accept a potential undefined if there is a generic argument
|
||||
// $ExpectError
|
||||
React.useRef<number>(undefined);
|
||||
// make sure once again there's no |undefined if the initial value doesn't either
|
||||
// $ExpectType MutableRefObject<number>
|
||||
React.useRef<number>(1);
|
||||
// and also that it is not getting erased if the parameter is wider
|
||||
// $ExpectType MutableRefObject<number | undefined>
|
||||
React.useRef<number | undefined>(1);
|
||||
|
||||
// should be contextually typed
|
||||
const a: React.MutableRefObject<number | undefined> = React.useRef(undefined);
|
||||
const b: React.MutableRefObject<number | undefined> = React.useRef();
|
||||
const c: React.MutableRefObject<number | null> = React.useRef(null);
|
||||
const d: React.RefObject<number> = React.useRef(null);
|
||||
|
||||
const id = React.useMemo(() => Math.random(), []);
|
||||
React.useImperativeHandle(ref, () => ({ id }), [id]);
|
||||
@ -110,6 +147,10 @@ function useEveryHook(ref: React.Ref<{ id: number }>|undefined): () => boolean {
|
||||
// $ExpectError
|
||||
React.useImperativeMethods(ref, () => ({}), [id]);
|
||||
|
||||
// make sure again this is not going to the |null convenience overload
|
||||
// $ExpectType MutableRefObject<boolean>
|
||||
const didLayout = React.useRef(false);
|
||||
|
||||
React.useLayoutEffect(() => {
|
||||
setState(1);
|
||||
setState(prevState => prevState - 1);
|
||||
@ -140,6 +181,29 @@ function useEveryHook(ref: React.Ref<{ id: number }>|undefined): () => boolean {
|
||||
React.useDebugValue(id, value => value.toFixed());
|
||||
React.useDebugValue(id);
|
||||
|
||||
// allow passing an explicit undefined
|
||||
React.useMemo(() => {}, undefined);
|
||||
// but don't allow it to be missing
|
||||
// $ExpectError
|
||||
React.useMemo(() => {});
|
||||
|
||||
// useState convenience overload
|
||||
// default to undefined only (not that useful, but type-safe -- no {} or unknown!)
|
||||
// $ExpectType undefined
|
||||
React.useState()[0];
|
||||
// $ExpectType number | undefined
|
||||
React.useState<number>()[0];
|
||||
// default overload
|
||||
// $ExpectType number
|
||||
React.useState(0)[0];
|
||||
// $ExpectType undefined
|
||||
React.useState(undefined)[0];
|
||||
// make sure the generic argument does reject actual potentially undefined inputs
|
||||
// $ExpectError
|
||||
React.useState<number>(undefined)[0];
|
||||
|
||||
// useReducer convenience overload
|
||||
|
||||
return React.useCallback(() => didLayout.current, []);
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user