0
# @mui/types
1
2
@mui/types provides essential TypeScript utility types and interfaces specifically designed for Material UI components and the broader React ecosystem. It includes advanced type manipulation utilities, overridable component interfaces, prop injection patterns, and string union generation helpers that enable robust type safety and component composition patterns.
3
4
## Package Information
5
6
- **Package Name**: @mui/types
7
- **Package Type**: npm
8
- **Language**: TypeScript
9
- **Installation**: `npm install @mui/types`
10
11
## Core Imports
12
13
```typescript
14
import {
15
DistributiveOmit,
16
OverridableComponent,
17
OverridableTypeMap,
18
PropInjector,
19
Simplify,
20
expectType
21
} from "@mui/types";
22
```
23
24
For CommonJS:
25
26
```javascript
27
const {
28
DistributiveOmit,
29
OverridableComponent,
30
PropInjector
31
} = require("@mui/types");
32
```
33
34
## Basic Usage
35
36
```typescript
37
import {
38
OverridableComponent,
39
OverridableTypeMap,
40
DistributiveOmit,
41
Simplify
42
} from "@mui/types";
43
44
// Define a component with overridable root element
45
interface ButtonTypeMap extends OverridableTypeMap {
46
props: {
47
variant?: "contained" | "outlined" | "text";
48
disabled?: boolean;
49
};
50
defaultComponent: "button";
51
}
52
53
// Create an overridable component type
54
const Button: OverridableComponent<ButtonTypeMap> = {} as any;
55
56
// Usage with default component (button)
57
<Button variant="contained" disabled onClick={() => {}} />
58
59
// Usage with custom component (a)
60
<Button component="a" href="/home" variant="outlined" />
61
62
// Type utilities
63
type CleanProps = DistributiveOmit<{ a: string; b: number; c: boolean }, "b" | "c">;
64
// Result: { a: string }
65
66
type SimpleType = Simplify<{ a: string } & { b: number }>;
67
// Result: { a: string; b: number }
68
```
69
70
## Architecture
71
72
@mui/types is built around several key patterns:
73
74
- **Component Polymorphism**: The `component` prop pattern allowing flexible component composition
75
- **Type Safety**: Advanced TypeScript utilities for maintaining strict typing during composition
76
- **Prop Injection**: Higher-order component patterns with type-safe prop manipulation
77
- **Distributive Operations**: Type utilities that work correctly with union types
78
- **Testing Utilities**: Type-level testing and validation helpers
79
80
## Capabilities
81
82
### Type Manipulation Utilities
83
84
Core TypeScript utilities for advanced type operations and manipulation.
85
86
```typescript { .api }
87
/**
88
* Remove properties K from T, distributive for union types
89
*/
90
type DistributiveOmit<T, K extends keyof any> = T extends any ? Omit<T, K> : never;
91
92
/**
93
* Like T & U, but using value types from U where properties overlap
94
*/
95
type Overwrite<T, U> = DistributiveOmit<T, keyof U> & U;
96
97
/**
98
* Simplifies display of a type without modifying it
99
*/
100
type Simplify<T> = T extends Function ? T : { [K in keyof T]: T[K] };
101
102
/**
103
* Changes properties K from T to required
104
*/
105
type PartiallyRequired<T, K extends keyof T> = DistributiveOmit<T, K> & {
106
[P in K]-?: T[P];
107
};
108
109
/**
110
* Generate string literal types with default record T and override record U
111
*/
112
type OverridableStringUnion<T extends string | number, U = {}> = GenerateStringUnion<
113
Overwrite<Record<T, true>, U>
114
>;
115
```
116
117
### Component Polymorphism
118
119
Advanced component patterns enabling the `component` prop for flexible component composition.
120
121
```typescript { .api }
122
/**
123
* A component whose root component can be controlled via a component prop
124
*/
125
interface OverridableComponent<M extends OverridableTypeMap> {
126
<C extends React.ElementType>(
127
props: {
128
/**
129
* The component used for the root node.
130
* Either a string to use a HTML element or a component.
131
*/
132
component: C;
133
} & OverrideProps<M, C>,
134
): React.JSX.Element | null;
135
(props: DefaultComponentProps<M>): React.JSX.Element | null;
136
propTypes?: any;
137
}
138
139
/**
140
* Base interface for overridable component type mapping
141
*/
142
interface OverridableTypeMap {
143
props: {};
144
defaultComponent: React.ElementType;
145
}
146
147
/**
148
* Props when component={Component} is used
149
*/
150
type OverrideProps<
151
M extends OverridableTypeMap,
152
C extends React.ElementType
153
> = (
154
& BaseProps<M>
155
& DistributiveOmit<React.ComponentPropsWithRef<C>, keyof BaseProps<M>>
156
);
157
158
/**
159
* Props when component={Component} is NOT used
160
*/
161
type DefaultComponentProps<M extends OverridableTypeMap> =
162
& BaseProps<M>
163
& DistributiveOmit<React.ComponentPropsWithRef<M['defaultComponent']>, keyof BaseProps<M>>;
164
165
/**
166
* Props defined on the component from the type map
167
*/
168
type BaseProps<M extends OverridableTypeMap> = M['props'];
169
```
170
171
### Prop Injection Patterns
172
173
Higher-order component utilities for type-safe prop injection and manipulation.
174
175
```typescript { .api }
176
/**
177
* Ensures overlapping properties between T and U have non-conflicting value types
178
*/
179
type ConsistentWith<DecorationTargetProps, InjectedProps> = {
180
[P in keyof DecorationTargetProps]: P extends keyof InjectedProps
181
? InjectedProps[P] extends DecorationTargetProps[P]
182
? DecorationTargetProps[P]
183
: InjectedProps[P]
184
: DecorationTargetProps[P];
185
};
186
187
/**
188
* A function that takes {component} and returns a component that passes along
189
* all props to {component} except the {InjectedProps} and accepts additional {AdditionalProps}
190
*/
191
type PropInjector<InjectedProps, AdditionalProps = {}> = <
192
C extends React.JSXElementConstructor<ConsistentWith<React.ComponentProps<C>, InjectedProps>>,
193
>(
194
component: C,
195
) => React.JSXElementConstructor<
196
DistributiveOmit<
197
React.JSX.LibraryManagedAttributes<C, React.ComponentProps<C>>,
198
keyof InjectedProps
199
> &
200
AdditionalProps
201
>;
202
```
203
204
### Type Testing Utilities
205
206
Tools for type-level testing and validation in TypeScript projects.
207
208
```typescript { .api }
209
/**
210
* Conditional type for exact type equality checking
211
*/
212
type IfEquals<T, U, Y = unknown, N = never> =
213
(<G>() => G extends T ? 1 : 2) extends <G>() => G extends U ? 1 : 2 ? Y : N;
214
215
/**
216
* Issues a type error if Expected is not identical to Actual
217
* @param actual - Value to test, should be typeof value statement
218
*/
219
declare function expectType<Expected, Actual>(
220
actual: IfEquals<Actual, Expected, Actual>,
221
): void;
222
```
223
224
## Usage Examples
225
226
### Creating Overridable Components
227
228
```typescript
229
import { OverridableComponent, OverridableTypeMap } from "@mui/types";
230
231
// Define your component's type map
232
interface MyComponentTypeMap extends OverridableTypeMap {
233
props: {
234
color?: "primary" | "secondary";
235
size?: "small" | "medium" | "large";
236
};
237
defaultComponent: "div";
238
}
239
240
// Use the type in your component definition
241
const MyComponent: OverridableComponent<MyComponentTypeMap> =
242
React.forwardRef((props, ref) => {
243
const { component: Component = "div", color, size, ...other } = props;
244
return <Component ref={ref} {...other} />;
245
});
246
247
// Usage
248
<MyComponent color="primary" /> // renders as div
249
<MyComponent component="section" color="secondary" /> // renders as section
250
<MyComponent component="a" href="/link" color="primary" /> // renders as anchor with href
251
```
252
253
### Higher-Order Component with Prop Injection
254
255
```typescript
256
import { PropInjector, ConsistentWith } from "@mui/types";
257
258
interface ThemeProps {
259
theme: {
260
primaryColor: string;
261
backgroundColor: string;
262
};
263
}
264
265
// Create a HOC that injects theme props
266
const withTheme: PropInjector<ThemeProps> = (Component) => {
267
return (props) => {
268
const theme = {
269
primaryColor: "#1976d2",
270
backgroundColor: "#ffffff",
271
};
272
return <Component {...props} theme={theme} />;
273
};
274
};
275
276
// Use with any component
277
const MyButton = (props: { label: string; theme: ThemeProps["theme"] }) => (
278
<button style={{ color: props.theme.primaryColor }}>
279
{props.label}
280
</button>
281
);
282
283
const ThemedButton = withTheme(MyButton);
284
// Usage: <ThemedButton label="Click me" /> (theme is automatically injected)
285
```
286
287
### Type Manipulation
288
289
```typescript
290
import { DistributiveOmit, Overwrite, Simplify, PartiallyRequired } from "@mui/types";
291
292
interface User {
293
id: number;
294
name: string;
295
email: string;
296
isActive: boolean;
297
}
298
299
// Remove sensitive fields for public API
300
type PublicUser = DistributiveOmit<User, "email" | "isActive">;
301
// Result: { id: number; name: string }
302
303
// Override specific properties
304
type UserWithStringId = Overwrite<User, { id: string }>;
305
// Result: { id: string; name: string; email: string; isActive: boolean }
306
307
// Simplify complex intersection types
308
type ComplexType = { a: string } & { b: number } & { c: boolean };
309
type SimpleType = Simplify<ComplexType>;
310
// Result: { a: string; b: number; c: boolean }
311
312
// Make specific properties required
313
type UserWithRequiredEmail = PartiallyRequired<Partial<User>, "email">;
314
// Result: { id?: number; name?: string; email: string; isActive?: boolean }
315
```
316
317
### Type Testing
318
319
```typescript
320
import { expectType, IfEquals } from "@mui/types";
321
322
// Test exact type equality
323
const value = "hello";
324
expectType<string, typeof value>(value); // ✓ passes
325
// expectType<number, typeof value>(value); // ✗ type error
326
327
// Conditional type checking
328
type IsString<T> = IfEquals<T, string, "yes", "no">;
329
type Test1 = IsString<string>; // "yes"
330
type Test2 = IsString<number>; // "no"
331
```