# TypeScript

# Usage with TypeScript

All `@mantine/*` packages are fully compatible with TypeScript. All examples in the documentation
are written in TypeScript – you can copy and paste them to your project without any changes.

This guide will help you get familiar with the types that the `@mantine/core` package exports.

## Components props types

Each `@mantine/` package that exports components also exports props types for these components.
You can import component props types by adding `Props` to the component name.
For example, you can import Button and DatePicker component props like this:

```tsx
import type { ButtonProps } from '@mantine/core';
import type { DatePickerProps } from '@mantine/dates';
```

Note that there are two variations of props types: for polymorphic components and for regular components.
Regular component props types include `React.ComponentProps<'X'>`, where `X` is the root element
type, for example `'div'`.

Example of extending regular component props:

```tsx
import { Group, GroupProps } from '@mantine/core';

// Interface includes `React.ComponentProps<'div'>`
interface MyGroupProps extends GroupProps {
  spacing: number;
}

function MyGroup({ spacing, ...others }: MyGroupProps) {
  return <Group my={spacing} {...others} />;
}
```

## Polymorphic components props types

[Polymorphic component](https://mantine.dev/llms/guides-polymorphic.md) props types don't include `React.ComponentProps<'X'>`
because their root element depends on the `component` prop value.

Example of extending [polymorphic component](https://mantine.dev/llms/guides-polymorphic.md) props:

```tsx
import { Button, ButtonProps, ElementProps } from '@mantine/core';

interface MyButtonProps
  extends ButtonProps,
    ElementProps<'button', keyof ButtonProps> {
  height: number;
}

function MyButton({ height, ...others }: MyButtonProps) {
  return <Button style={{ height }} {...others} />;
}
```

## Namespace types

All Mantine components export namespaces with related types. For example, [Button](https://mantine.dev/llms/core-button.md)
component props can be accessed as `Button.Props`:

```tsx
import {  Button } from '@mantine/core';

// Same as `import type { ButtonProps } from '@mantine/core';`
type MyButtonProps = Button.Props;
```

## ElementProps type

`ElementProps` is a utility type similar to `React.ComponentProps`, but with additional
features. It replaces the native element's `style` prop with Mantine's [style prop](https://mantine.dev/llms/styles-style.md) and
allows omitting properties that are passed as a second type.

```tsx
import { ButtonProps, ElementProps } from '@mantine/core';

// Equivalent of `React.ComponentProps<'button'>`
type ButtonElementProps = ElementProps<'button'>;

// Equivalent of `Omit<React.ComponentProps<'button'>, 'color' | 'onClick'>`
type OmitColor = ElementProps<'button', 'color' | 'onClick'>;

// Removes all Mantine component props from React component props
// to avoid props types conflicts
// Equivalent of `Omit<React.ComponentProps<'button'>, keyof ButtonProps>`
type OmitButtonProps = ElementProps<'button', keyof ButtonProps>;
```

## MantineTheme type

`MantineTheme` is a type of the [theme object](https://mantine.dev/llms/theming-theme-object.md). You can use it to add types
to functions that accept a theme object as an argument:

```tsx
import { MantineTheme, useMantineTheme } from '@mantine/core';

function getPrimaryColor(theme: MantineTheme) {
  return theme.colors.blue[5];
}

function Demo() {
  const theme = useMantineTheme();
  return <div style={{ color: getPrimaryColor(theme) }} />;
}
```

## MantineThemeOverride type

`MantineThemeOverride` type is a deep partial of `MantineTheme`. It can be used in functions
that accept a theme override as an argument:

```tsx
import {
  createTheme,
  MantineThemeOverride,
  mergeThemeOverrides,
} from '@mantine/core';

const baseTheme = createTheme({
  fontFamily: 'Helvetica, sans-serif',
});

function mergeThemes(themes: MantineThemeOverride[]) {
  return mergeThemeOverrides(baseTheme, ...themes);
}

const overrideTheme = createTheme({
  primaryColor: 'blue',
});

const overrideTheme2 = createTheme({
  cursorType: 'pointer',
});

const mergedTheme = mergeThemes([overrideTheme, overrideTheme2]);
```

## MantineColorScheme type

`MantineColorScheme` is a union of `'light' | 'dark' | 'auto'` values. You can use it to add types
to functions that accept color scheme as an argument:

```tsx
import {
  MantineColorScheme,
  useMantineColorScheme,
} from '@mantine/core';

function getComputedColorScheme(colorScheme: MantineColorScheme) {
  return colorScheme === 'auto' ? 'light' : colorScheme;
}

function Demo() {
  const { colorScheme } = useMantineColorScheme();
  const computed = getComputedColorScheme(colorScheme);
}
```

## MantineSize type

`MantineSize` type is a union of `'xs' | 'sm' | 'md' | 'lg' | 'xl'` values. You can use it to add types
to various props that accept size as an argument, for example, `radius`, `shadow`, `p`.

```tsx
import { MantineSize, Paper } from '@mantine/core';

interface DemoProps {
  size: MantineSize;
  radius: MantineSize | (string & {}) | number;
  shadow: MantineSize | string;
}

function Demo({ size, radius, shadow }: DemoProps) {
  return <Paper radius={radius} shadow={shadow} p={size} m={size} />;
}
```

## Theme object declarations

You can change `theme.other` and `theme.colors` types by extending the `MantineTheme` interface
in a `.d.ts` file. Create `mantine.d.ts` anywhere in your project (must be included in `tsconfig.json`)
to extend theme object types.

To override `theme.other`:

```tsx
// mantine.d.ts
declare module '@mantine/core' {
  export interface MantineThemeOther {
    myCustomProperty: string;
    myCustomFunction: () => void;
  }
}
```

To override `theme.colors`:

```tsx
import {
  DefaultMantineColor,
  MantineColorsTuple,
} from '@mantine/core';

type ExtendedCustomColors =
  | 'primaryColorName'
  | 'secondaryColorName'
  | DefaultMantineColor;

declare module '@mantine/core' {
  export interface MantineThemeColorsOverride {
    colors: Record<ExtendedCustomColors, MantineColorsTuple>;
  }
}
```

You can also customize size-related types for `theme.spacing`, `theme.radius`,
`theme.breakpoints`, `theme.fontSizes`, `theme.lineHeights`, and `theme.shadows` similarly.

To override `theme.spacing` and `theme.radius`

```tsx
import {
  DefaultMantineSize,
  MantineThemeSizesOverride,
} from '@mantine/core';

type ExtendedCustomSpacing =
  | 'xxl'
  | 'xxxs'
  | DefaultMantineSize;

type ExtendedCustomRadius =
  | 'xxs'
  | DefaultMantineSize;

declare module '@mantine/core' {
  export interface MantineThemeSizesOverride {
    spacing: Record<ExtendedCustomSpacing, string>;
    radius: Record<ExtendedCustomRadius, string>;
  }
}
```

Note that extending the theme type isn't required; it's only needed if you want to
make your theme object types more strict and add autocomplete in your editor.

## Custom variants types

You can define types for custom [variants](https://mantine.dev/llms/styles-variants-sizes.md) by
extending the `{x}Props` interface with the new variant type in your `mantine.d.ts` file.

Example of adding a custom variant type to the [Button](https://mantine.dev/llms/core-button.md) component:

```tsx
import { ButtonVariant, MantineSize } from '@mantine/core';

type ExtendedButtonVariant = ButtonVariant | 'contrast' | 'radial-gradient';

declare module '@mantine/core' {
  export interface ButtonProps {
    variant?: ExtendedButtonVariant;
  }
}
```
