Home > Blockchain >  typescript check if two const objects have the same shape
typescript check if two const objects have the same shape

Time:08-25

I have two theme objects:

const lightMode = {
  background: "white",
  text: {
    primary: "dark",
    secondary: "darkgrey"
  },
} as const

const darkMode = {
  background: "black",
  text: {
    primary: "white",
  },
} as const

I want to get a type error if the lightMode object (default theme, which everyone will modify first) does not have the same shape as the darkMode object.

This will help people remember to update darkMode with some color values, if they add some new theme color to lightMode.

CodePudding user response:

You're overthinking this.

What you have a type that both object must implement to be correct. Like most things in Typescript, defining good data types up front will make things nice for you in the long run.

Make a type like:

type UITheme = {
    background: string,
    text: {
        primary: string
        secondary: string
    }
}

And now use it to make sure your objects are made properly.

const lightMode: UITheme = {
  background: "white",
  text: {
    primary: "dark",
    secondary: "darkgrey"
  },
} as const

const darkMode: UITheme = {
  background: "black",
  text: {
    primary: "white",
  },
} as const
// Property 'secondary' is missing in type
//   '{ readonly primary: "white"; }'
// but required in type
//   '{ primary: string; secondary: string; }'.

See playground


Or if you need the string literal types inferred, then use a generic function to create the objects and enforce the types.

type UITheme = {
    background: string,
    text: {
        primary: string
        secondary: string
    }
}

const createUIMode = <T extends UITheme>(theme: T) => theme

const lightMode = createUIMode({
  background: "white",
  text: {
    primary: "dark",
    secondary: "darkgrey"
  },
} as const)

const darkMode = createUIMode({
  background: "black",
  text: {
    primary: "white",
  },
} as const)
// error

See playground

CodePudding user response:

Here's my first attempt:

type NormalizeThemeConstType<someTheme extends object> = Writable<
  Schema<someTheme, string>
>;

const testAssignment: NormalizeThemeConstType<typeof darkMode> =
  lightTheme as NormalizeThemeConstType<typeof lightMode>;

The type errors seem crazy at first, but as is usually the case, looking at the end of the error revealed, on of our themes is missing a property from the other!

  • Related