LazioTibijczyk
LazioTibijczyk

Reputation: 1937

Destructure using rest parameters

I am trying to destructure a React context based on rest parameters passed to the hook.

Say I am passing an array of enums and want to return only the ones that are passed into the hook.

Here's my interface context type

enum ConfigItem {
  SomeItem = 'SomeItem',
  AnotherItem = 'AnotherItem',
}

type Config = Record<ConfigItem, boolean>;

type ConfigState = {
  config: Config;
}

and the hook itself

const useConfig = (...configArgs: ConfigItem) => {
  const configContext = useContext(ConfigContext);
  
  const { config } = configContext;
  const { ...configArgs } = config;  // Duplicate identifier 'configArgs'.

  return configArgs;
}

I would like to use it like so

const config = useConfig(ConfigItem.SomeItem, ConfigItem.AnotherItem);

and that would return an object with relevant properties. I might want to pass a single arg but potentially many.

The above const would return this (true/false is whatever would be in the context but that is not in scope of the question)

{
  SomeItem: true/false,
  AnotherItem: true/false,
}

but if I would only pass one of them I expect to see a single property.

Upvotes: 1

Views: 127

Answers (1)

T.J. Crowder
T.J. Crowder

Reputation: 1074335

By their nature, rest parameters are arrays, so you need an array type:

const useConfig = (...configArgs: ConfigItem[]) => {
//                                          ^^−−−−−−−−−−−−−−−−−−−−−−−−−
// ...

If you pass just one argument, the array will have one element, but it will still be an array.


In a comment you've said:

My problem is how to return only the provided args properties but thanks for the correction.

If you mean you're having trouble creating the object you want to return, you can do that in a few ways; I'd probably lean toward Object.fromEntries (you'll need to polyfill if targeting pre-ES2019 environments):

const useConfig = (...configArgs: ConfigItem[]) => {
    const configContext = useContext(ConfigContext);
    
    const { config } = configContext;
    return Object.fromEntries(
        configArgs.map(itemKey => [itemKey, config[itemKey]])
    ) as Record<ConfigItem, boolean>;
};

You may need a type guard to avoid

Upvotes: 2

Related Questions