Home > OS >  How to type a function parameter 'value' in order to always match the type of a dynamic &#
How to type a function parameter 'value' in order to always match the type of a dynamic &#

Time:09-28

I have an object, whose keys' types can be string | number | boolean. In order to update this object I have an abstract function that accepts two parameters:

  1. key: to target a specific key of the object
  2. value: to update the value of the aforementioned key.

The function looks like this:

  // interface 
  interface Frequency {
frequency: "daily" | "monthly";
sendHour: number;
sendMinutes: number;
sendDay: number;
delayStart: boolean;
}

  // react state
  const [frequency, setFrequency] = useState<Frequency>({
    frequency: "daily",
    sendHour: 1,
    sendMinutes: 1,
    sendDay: 1,
    delayStart: false,
  });
  
  
  // updater
  const onChangeFrequency = (
    key: keyof Frequency,
    value: string | number | boolean
  ) => {
    setFrequency((frequency) => ({
      ...frequency,
      [key]: value,
    }));
  };

It works, but it also means I coud overwrite a boolean with a number, and typescript would not catch the error. How to make sure the value I enter always match the key's type?

CodePudding user response:

You can do this with generics if you're using a literal for the key when calling onChangeFrequency:

const onChangeFrequency = <KeyType extends keyof Frequency,>(
// −−−−−−−−−−−−−−−−−−−−−−−^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    key: KeyType,
// −−−−−−^^^^^^^
    value: Frequency[KeyType]
// −−−−−−−−^^^^^^^^^^^^^^^^^^
) => {
    setFrequency((frequency) => ({
        ...frequency,
        [key]: value,
    }));
};

onChangeFrequency("sendHour", 20);      // Works
onChangeFrequency("sendHour", "daily"); // Error as desired

Playground link

(The , at the end of the generic is just in case you're doing this in a .tsx file; it differentiates between generic parameter syntax and JSX element syntax.)

  • Related