简体   繁体   中英

Typescript not reading the correct type

I have this React hook:

import { ChangeEvent, RefObject, useEffect, useState } from "react";

type OriginalOnchange = (e: ChangeEvent<HTMLInputElement>) => void;
type OnchangeEvent = ChangeEvent<HTMLInputElement>;
export type OnChangeWrapper = (originalOnchange?: OriginalOnchange) => (onchangeEvent: OnchangeEvent) => void;

export const useTrackValidity = (
  inputRef: RefObject<HTMLInputElement | undefined>,
  value: string,
  invalidInputMessage?: string
) => {
  const [isValid, setIsValid] = useState<boolean>();

  const onChangeWrapper: OnChangeWrapper = (originalOnchange?: OriginalOnchange) => (onChangeEvent: OnchangeEvent) => {
    setIsValid(!(!!invalidInputMessage || !onChangeEvent.currentTarget.validity.valid));
    if (!!originalOnchange) {
      originalOnchange(onChangeEvent);
    }
  };

  useEffect(() => {
    if (inputRef.current) {
      inputRef.current.setCustomValidity(invalidInputMessage || "");
      setIsValid(!(!!invalidInputMessage || !inputRef.current.validity.valid));
    }
  }, [inputRef, invalidInputMessage, value]);

  return [isValid, onChangeWrapper];
};

When I call it like this:

 const [isValid, onChangeWrapper] = useTrackValidity(inputRef, value?.toString() ?? "", invalidInputMessage);

  return (
    <StyledInput
      ref={inputRef}
      type={inputType || type}
      name={inputName || name}
      required={isRequired || required}
      onChange={onChangeWrapper(onChange)}
      onBlur={onChangeWrapper()}
      isValid={isValid}
      value={value}
      {...props}
    />
  );

I get this error:

TS2349: This expression is not callable.
  Not all constituents of type 'boolean | OnChangeWrapper' are callable.
    Type 'false' has no call signatures. TS2722: Cannot invoke an object which is possibly 'undefined'. 

whenever I call onChangeWrapper .

When I change the above to this:

const [isValid, onChangeWrapper] = useTrackValidity(inputRef, value?.toString() ?? "", invalidInputMessage) as [
    boolean | undefined,
    OnChangeWrapper
  ];

It does work, which strikes me as odd because I basically reiterated the return type.

TypeScript infers that the returned array will be Array<boolean|yourfunctiontype> — that is, that all elements will be the intersection of those types. boolean isn't callable, so you can't call any of the elements without some kind of guard.

To solve it, tell TypeScript that your hook function returns [boolean, yourFunctionType] , specifically:

type onChangeWrapperType = /*...the function type here...*/;

// ...

export const useTrackValidity = (
  // ...
): [boolean, onChangeWrapperType] => {
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^−−−−−−−−−−−−−−−−−−−−−−−−−− here
    // ...
    const onChangeWrapper: onChangeWrapperType = /*...*/;
    // ...
    return [isVaild, onChangeWrapper];
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM