cherrypick types in typescript when calling an external library function

Viewed 65

I am trying to use a helper function from a library with a strict type in typescript but I can't seem to get it to work.

For instance, the following code from chakraui.

export interface BaseBreakpointConfig {
  sm: string
  md: string
  lg: string
  xl: string
  "2xl"?: string
  [key: string]: string | undefined
}

export type Breakpoints<T> = T & { base: "0em" }

export const createBreakpoints = <T extends BaseBreakpointConfig>(
  config: T,
): Breakpoints<T> => {
  warn({
    condition: true,
    message: [
      `[chakra-ui]: createBreakpoints(...) will be deprecated pretty soon`,
      `simply pass the breakpoints as an object. Remove the createBreakpoint(..) call`,
    ].join(""),
  })
  return { base: "0em", ...config }
}

And I want to call the createBreakpoints function without supplying all the keys, how would I do that? Is that possible?

I tried using the Pick utility but that didn't help.

type Breakpoints = Pick<BaseBreakpointConfig, 'sm' | 'md' | 'lg'>

const breakpoints = createBreakPoints<Breakpoints>({
  sm: "...",
  md: "...",
  lg: "..."
});

I got the Property "xl" is missing in type "Breakpoints" but required in type BaseBreakpointConfig error

1 Answers

Using Partial<Type>, which returns a type where every property of Type is optional, we can make T extend Partial<BaseBreakpointConfig>. This will make createBreakpoints() accept arguments with types are subsets of BaseBreakpointConfig, like Pick<BaseBreakpointConfig, 'sm' | 'md' | 'lg'>:

export const createBreakpoints = <T extends Partial<BaseBreakpointConfig>>(
  config: T,
): Breakpoints<T> => {
  // ...
};

const breakpoints = createBreakpoints<Pick<BaseBreakpointConfig, 'sm' | 'md' | 'lg'>>({
  sm: "...",
  md: "...",
  lg: "..."
}); // works

TypeScript playground

Related