Home > database >  How to define the properties of a useState object having extended type and returned by a function, w
How to define the properties of a useState object having extended type and returned by a function, w

Time:01-16

I am experiencing with using TypeScript in React states. My intention is to use objects with strict types instead of several separate useState statements, and with desirably no additional classes to represent these object structures (only interfaces). I have the following scenario:

const [state, setState] = useState<IStateType>(..code1..);

In the above line IStateType extends another interface, let us call that IStateSubType:

export interface IStateType extends IStateSubType {...}

Since objects with IStateSubType are instantiated more than once in my project, I would create a function to initialise these objects in order to reduce code redundancy:

function getEmptyStateSubType(): IStateSubType(..code2..);

In this function code2 part would define the properties required by IStateSubType and return the resulting object. I would call getEmptyStateSubType() in code1 part, then I would extend its returning objects' properties with missing ones required by IStateType as below:

const [state, setState] = useState<IStateType>(
  (): IStateType => {
    const tmpValue: IStateSubType = getEmptyStateSubType();
    const value: IStateType = {
      ...tmpValue,
      foo: bar
    };
    return value;
  }
);

Using the above implementation I did achieve my goal to strictly use types in both the state and the function and there are also no redundant lines, but at the end of the day not only did the number of lines increased in my code, but I also feel that readability decreased greatly while unnecessary complexity increased. I was wondering if there are better solutions to achieve my goals: maintain readability and enforce type usage. How to implement this with shorter and more readable code?

CodePudding user response:

This should do

const [state, setState] = useState<IStateType>(
    () => ({...getEmptyStateSubType(), foo: 'bar' })
);

But nothing stops you from creating a getStateType function

const getStateType =
    (o: Omit<IStateType, keyof IStateSubType>): IStateType =>
        (({...getEmptyStateSubType(), ...o}))

const [state, setState] = useState<IStateType>(getStateType({ foo: 'bar' }));

CodePudding user response:

Though my question was quite vague, for anyone facing similar issues in the future allow me to share my second attempt for implementing this:

const [state, setState] = useState<IStateType>(
  () => { // I removed the type, since it is already enforced by useState
    const value: IStateType = {
      ...getEmptyStateSubType(), // I used spread on method return value
      foo: bar
    };
    return value;
  }
);
  • Related