Home > Blockchain >  Why does destructuring props in react with Typescript function require passing an object?
Why does destructuring props in react with Typescript function require passing an object?

Time:10-19

I have recently started using react with typescript and it seems like something odd is happening when I destructure props with optional / default values. For example take this function to generate a random id:

interface GenKeyIdProps {
  length?: number;
}

/**
 * Generate a random id (mainly for use with rendering lists of components.
 * genKeyId convert Math.random to base 36 (numbers   letters), and grab the first ${lenght} characters after the decimal.
 * @param length (optional) specify how many characters the id should be. default is 5.
 * @returns a string with number and letters of specified length.
 */
export const genKeyId = ({ length = 5 }: GenKeyIdProps) => Math.random().toString(36).substr(2, length);

The problem is when I try to call it:

import { genKeyId } from '../../../helpers';

interface TextWrapperProps {
  textLines: string[];
}

const TextWrapper = ({ textLines }: TextWrapperProps) => {

  return textLines.map(line => (<div key={genKeyId()}>{line}</div>));

};

export default TextWrapper;

if I do not pass at least an empty object to genKeyId I get the following error: Expected 1 arguments, but got 0.ts(2554).

Why do I need to pass an empty object? Is my GenKeyIdProps interface specifying the props need to be part of an object? I am a bit confused about this.

CodePudding user response:

Is my GenKeyIdProps interface specifying the props need to be part of an object?

Yes, you've defined GenKeyIdProps as an object. All interface definitions are objects. Your GenKeyIdProps is roughly equivalent to:

type GenKeyIdProps = {
  length?: number;
};

That is, an object with an optional length property of type number.

There's no need for genKeyId to accept an object, though; it's not a component function, it's just a utility function. You could define it to accept length directly by removing the destructuring:

export const genKeyId = (length = 5) => Math.random().toString(36).substr(2, length);

Alternatively, if you do want it to accept an object but you want it to be able to be called without one, you can default the parameter you're destructuring:

export const genKeyId = ({ length = 5 }: GenKeyIdProps = {}) => Math.random().toString(36).substr(2, length);
// −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−^^^^^

Now you can call genKeyId A) with an object that has a length; B) with an object that doesn't have a length; and C) with no argument at all.

It's up to you whether you want getKeyId to accept a number or an object with a length property.

  • Related