reactjs - Ongelmia TypeScriptin geneerisen tyypin määrittelyssä


Luo hookkia nimeltä useUpdate, ja minulla on ongelmia tyypin määrittämisessä, koodi näkyy alla

type CallBack<T extends readonly any[]> = (
  ...args: T
) => void | (() => void | undefined);

function useUpdate<T extends readonly any[]>(
  callback: CallBack<T>,
  deps: T
) {
  const didMount = useRef(false);
  const prevDeps = useRef(deps);

  useEffect(() => {
    if (!didMount.current) {
      didMount.current = true;

      return;
    }

    const clean = callback(...prevDeps.current);

    prevDeps.current = deps;

    return () => {
      if (clean) {
        clean();
      }
    };
  }, deps);
}

Kun sitä käytetään, ei ole ongelmaa, jos takaisinsoitolla on argumentteja, mutta jos takaisinsoitolle ei anneta argumentteja, depsin tyyppi on väärä

const state: boolean = useSomethingElse(); // get changable data from anywere else

// OK, no type error
useUpdate((prevState) => {
 console.log('I want to compare the current state and prevState', prevState, state);
},[state]);


useUpdate(() => {
 console.log('I only care about the current state', state);
},[state]); // Type error occurs on this line, the message is:
//  Argument of type '[boolean]' is not assignable to parameter of type '[]'.
//  Source has 1 element(s) but target allows only 0.ts(2345)

Tiedän, että se johtuu siitä, että TypeScript asettaa T:n callback-argumenteiksi, jotka ovat [] jos argumentteja ei ole annettu, mutta onko mitään tapaa saada TypeScript käyttämään depsin tyyppiä ja ohittamaan callback-argumenttien tyyppiä T:tä asetettaessa?

Vastaus #1

Kaksi tapaa, joilla voit korjata tämän:

(1) Tee deps ensimmäiseksi parametriksi, jotta se alkaa päättelemällä T deps:stä

(2) Käytä toista geneeristä tyyppiä callback varten:

function useUpdate<T extends readonly any[], Cb extends CallBack<T>>(
  callback: Cb,
  deps: T
) {