Next.js Discord

Discord Forum

Hey just Typescript best practices question

Answered
Rhinelander posted this in #help-forum
Open in Discord
Avatar
RhinelanderOP
What would be better way to define this? I think it's good. But it takes so much code for couple of simple options
import Link from 'next/link';

interface LogoProps {
  color?: 'dark' | 'light' | 'primary' | 'muted';
  size?: 'small' | 'normal' | 'large';
  href?: string;
}

function Logo({ color, size, href = '/' }: LogoProps) {
  let className = 'font-bold tracking-tighter';

  switch (color) {
    case 'dark':
      className += ' text-stone-950';
      break;
    case 'light':
      className += ' text-stone-50';
      break;
    case 'primary':
      className += ' text-blue-600';
      break;
    case 'muted':
      className += ' text-muted';
      break;
    default:
      className += ' text-stone-950';
      break;
  }

  switch (size) {
    case 'large':
      className += ' text-2xl xl:text-3xl';
      break;
    case 'normal':
      className += ' text-base xl:text-lg';
      break;
    case 'small':
      className += ' text-sm xl:text-base';
      break;
    default:
      className += ' text-base xl:text-lg';
      break;
  }

  return (
    <Link href={href}>
      <span className={className}>OpenRecipes</span>
    </Link>
  );
}

export default Logo;
Answered by Pearls
You could possibly do it like this, which removes the usage of switch statement.

import Link from 'next/link';

interface LogoProps {
  color?: 'dark' | 'light' | 'primary' | 'muted';
  size?: 'small' | 'normal' | 'large';
  href?: string;
}

function Logo({ color = 'dark', size = 'normal', href = '/' }: LogoProps) {
  const colorClassNames = {
    dark: 'text-stone-950',
    light: 'text-stone-50',
    primary: 'text-blue-600',
    muted: 'text-muted',
  };

  const sizeClassNames = {
    small: 'text-sm xl:text-base',
    normal: 'text-base xl:text-lg',
    large: 'text-2xl xl:text-3xl',
  };

  const className = `font-bold tracking-tighter ${colorClassNames[color]} ${sizeClassNames[size]}`;

  return (
    <Link href={href}>
      <span className={className}>OpenRecipes</span>
    </Link>
  );
}

export default Logo;
View full answer

10 Replies

Avatar
RhinelanderOP
Is there a better way to define this
 color?: 'dark' | 'light' | 'primary' | 'muted'; 
And define this without switch statement as it takes a lot of code to do that
  switch (color) {
    case 'dark':
      className += ' text-stone-950';
      break;
    case 'light':
      className += ' text-stone-50';
      break;
    case 'primary':
      className += ' text-blue-600';
      break;
    case 'muted':
      className += ' text-muted';
      break;
    default:
      className += ' text-stone-950';
      break;
  }
Avatar
You could possibly do it like this, which removes the usage of switch statement.

import Link from 'next/link';

interface LogoProps {
  color?: 'dark' | 'light' | 'primary' | 'muted';
  size?: 'small' | 'normal' | 'large';
  href?: string;
}

function Logo({ color = 'dark', size = 'normal', href = '/' }: LogoProps) {
  const colorClassNames = {
    dark: 'text-stone-950',
    light: 'text-stone-50',
    primary: 'text-blue-600',
    muted: 'text-muted',
  };

  const sizeClassNames = {
    small: 'text-sm xl:text-base',
    normal: 'text-base xl:text-lg',
    large: 'text-2xl xl:text-3xl',
  };

  const className = `font-bold tracking-tighter ${colorClassNames[color]} ${sizeClassNames[size]}`;

  return (
    <Link href={href}>
      <span className={className}>OpenRecipes</span>
    </Link>
  );
}

export default Logo;
Answer
Avatar
RhinelanderOP
also everytime I add to className I must do space and that makes my code prone to errors
className += ' text-stone-950'; 
Thanks. But I won't mark is as solution yet because I need couple of more fixes before marking it
I would love to get solution for this also.
Avatar
1. I added default values for color and size in the function parameters. This ensures that there will always be a value for color and size, removing the need for a default case in your switch or mapping.

2. The colorClasses and sizeClasses objects map the color and size props to their respective CSS classes. This replaces the switch statements and makes adding or removing a color or size easier.

3. The className is constructed by combining the base classes with the classes for color and size chosen by the props. This one-liner replaces the need for multiple lines of switch statements.
This code is not 'bad', its actually a pretty good way of doing it. There is not really a better way to do this.
Avatar
RhinelanderOP
Okay thank you!
Avatar
You`re welcome :D