I'm using Mui components with TypeScript and trying to build a helper function to generate extended variants.
import { ButtonProps, ButtonPropsSizeOverrides } from "@mui/material";
declare module "@mui/material/Button" {
interface ButtonPropsVariantOverrides {
light: true;
}
}
type ButtonVariant = ButtonProps["variant"];
const buttonVariants: readonly Exclude<ButtonVariant, undefined>[] = [
"contained",
"outlined",
"light",
"text",
] as const;
I have actually had this working for a while using a key: string
value for the object it returns:
const makeVariants = (): { [key: string]: () => void } => {
return {
light: () => {},
};
};
But I found a typo in one place, and that made me realize I should make this type-safe — instead of string
(effectively any string as a key), I should require that the key be a member of the buttonVariants
.
I naively tried this:
type VariantMakerKey = typeof buttonVariants[number];
const makeVariants = (): { [key in VariantMakerKey]: () => void } => {
return {
light: () => {},
};
};
But TypeScript is mad because I didn't return all the properties.
// Type '{ light: () => void; }' is missing the following properties from type
// '{ text: () => void;
// outlined: () => void;
// contained: () => void;
// light: () => void; }': text, outlined, contained
How can I make the object that returns only require a partial set of keys, so that if I define a key, it must be in buttonVariants
, but I'm not required to declare them all?
CodePudding user response:
Your mapped type constructs an object type containing all the members of buttonVariants
. We have to find a way to make them optional to stop the compiler from requiring all properties to be set.
Their are certain Mapping Modifiers which can change the result of a mapped type. The ?
modifier makes all properties optional.
const makeVariants = (): { [key in VariantMakerKey]?: () => void } => {
return {
light: () => {},
};
};