0
# Types
1
2
The @strapi/helper-plugin package provides comprehensive TypeScript interfaces and types for Strapi-specific data structures, API responses, component props, and system functionality. These types ensure type safety and developer experience across plugin development.
3
4
## Core Message & Translation Types
5
6
Types for internationalization and message handling throughout the Strapi admin interface.
7
8
```typescript { .api }
9
// Translation message interface extending react-intl
10
interface TranslationMessage extends MessageDescriptor {
11
values?: Record<string, PrimitiveType>;
12
}
13
14
// Base message descriptor from react-intl
15
interface MessageDescriptor {
16
id: string;
17
defaultMessage?: string;
18
description?: string;
19
}
20
21
// Primitive types for translation values
22
type PrimitiveType = string | number | boolean | null | undefined | Date;
23
```
24
25
**Usage Examples:**
26
27
```typescript
28
// Define translatable messages
29
const messages: TranslationMessage = {
30
id: 'plugin.my-plugin.button.save',
31
defaultMessage: 'Save Changes',
32
values: {
33
count: 5,
34
name: 'Article'
35
}
36
};
37
38
// Use with react-intl
39
const { formatMessage } = useIntl();
40
const text = formatMessage(messages);
41
```
42
43
## API Error Types
44
45
Union types for various API error responses that can occur in Strapi applications.
46
47
```typescript { .api }
48
// Union type covering all possible API errors
49
type ApiError =
50
| errors.ApplicationError
51
| errors.ForbiddenError
52
| errors.NotFoundError
53
| errors.NotImplementedError
54
| errors.PaginationError
55
| errors.PayloadTooLargeError
56
| errors.PolicyError
57
| errors.RateLimitError
58
| errors.UnauthorizedError
59
| errors.ValidationError
60
| errors.YupValidationError;
61
62
// Individual error type examples
63
interface ApplicationError {
64
name: 'ApplicationError';
65
message: string;
66
details?: Record<string, any>;
67
}
68
69
interface ValidationError {
70
name: 'ValidationError';
71
message: string;
72
details: {
73
errors: Array<{
74
path: string[];
75
message: string;
76
name: string;
77
}>;
78
};
79
}
80
81
interface ForbiddenError {
82
name: 'ForbiddenError';
83
message: string;
84
details?: Record<string, any>;
85
}
86
```
87
88
**Usage Examples:**
89
90
```typescript
91
// Handle different error types
92
const handleApiError = (error: ApiError) => {
93
switch (error.name) {
94
case 'ValidationError':
95
// Handle validation errors
96
error.details.errors.forEach(validationError => {
97
console.error(`Field ${validationError.path.join('.')}: ${validationError.message}`);
98
});
99
break;
100
case 'ForbiddenError':
101
// Handle permission errors
102
console.error('Access denied:', error.message);
103
break;
104
case 'ApplicationError':
105
// Handle general application errors
106
console.error('Application error:', error.message);
107
break;
108
default:
109
console.error('Unknown error:', error.message);
110
}
111
};
112
```
113
114
## Filter & Query Types
115
116
Types for data filtering, querying, and search operations.
117
118
```typescript { .api }
119
// Attribute-based filters
120
type AttributeFilter = Record<
121
string,
122
Record<EntityService.Params.Filters.Operator.Where, string | null>
123
>;
124
125
// Relation-based filters
126
type RelationFilter = Record<string, AttributeFilter>;
127
128
// Generic filter type
129
type Filter = AttributeFilter | RelationFilter;
130
131
// Filter operator interface
132
interface Operator {
133
value: EntityService.Params.Filters.Operator.Where;
134
intlLabel: MessageDescriptor;
135
}
136
137
// Comprehensive filter data configuration
138
interface FilterData {
139
name: string;
140
metadatas: {
141
label: string;
142
customOperators?: Array<{
143
intlLabel: { id: string; defaultMessage: string };
144
value: string;
145
}>;
146
customInput?: React.ComponentType;
147
options?: Array<{ label?: string; customValue: string }>;
148
uid?: string;
149
};
150
fieldSchema: {
151
type: Attribute.Any['type'];
152
options?: string[];
153
mainField?: {
154
name: string;
155
type?: Attribute.Any['type'];
156
};
157
};
158
trackedEvent?: TrackingEvent;
159
}
160
161
// Default filter input props
162
interface DefaultFilterInputsProps {
163
label?: string;
164
onChange: (value: string | null) => void;
165
options?: FilterData['fieldSchema']['options'] | FilterData['metadatas']['options'];
166
type: FilterData['fieldSchema']['type'];
167
value?: string | null;
168
}
169
```
170
171
**Usage Examples:**
172
173
```typescript
174
// Define filter configuration
175
const articleFilters: FilterData[] = [
176
{
177
name: 'title',
178
metadatas: {
179
label: 'Title',
180
customOperators: [
181
{
182
intlLabel: { id: 'filter.contains', defaultMessage: 'Contains' },
183
value: '$containsi'
184
}
185
]
186
},
187
fieldSchema: {
188
type: 'string'
189
}
190
},
191
{
192
name: 'category',
193
metadatas: {
194
label: 'Category',
195
uid: 'api::category.category'
196
},
197
fieldSchema: {
198
type: 'relation',
199
mainField: { name: 'name', type: 'string' }
200
}
201
}
202
];
203
204
// Create filter objects
205
const titleFilter: AttributeFilter = {
206
title: {
207
$containsi: 'react'
208
}
209
};
210
211
const categoryFilter: RelationFilter = {
212
category: {
213
name: {
214
$eq: 'Technology'
215
}
216
}
217
};
218
```
219
220
## Content Manager Types
221
222
Types specific to content management functionality (also covered in Content Manager documentation).
223
224
```typescript { .api }
225
// Base entity interface
226
interface Entity {
227
id: StrapiEntity.ID;
228
createdAt: string | null;
229
createdBy: User | null;
230
updatedAt: string | null;
231
updatedBy: User | null;
232
}
233
234
// Content type with optional entity fields and dynamic attributes
235
interface ContentType extends Partial<Entity> {
236
publishedAt?: string | null;
237
publishedBy?: User | null;
238
[key: string]: Attribute.GetValue<Attribute.Any> | null;
239
}
240
241
// User interface for content relations
242
interface User extends NonNullableObject<Entity> {
243
firstname?: string;
244
lastname?: string;
245
username?: string;
246
email?: string;
247
isActive: boolean;
248
blocked: boolean;
249
roles: [];
250
}
251
252
// Helper type for non-nullable object properties
253
type NonNullableObject<T> = {
254
[key in keyof T]: NonNullable<T[key]>;
255
};
256
```
257
258
**Usage Examples:**
259
260
```typescript
261
// Work with content types
262
const article: ContentType = {
263
id: 1,
264
title: 'My Article',
265
content: 'Article content...',
266
publishedAt: '2023-01-01T00:00:00.000Z',
267
createdAt: '2023-01-01T00:00:00.000Z',
268
updatedAt: '2023-01-01T00:00:00.000Z'
269
};
270
271
// Type-safe property access
272
const title: string = article.title as string;
273
const isPublished: boolean = !!article.publishedAt;
274
```
275
276
## Component Prop Types
277
278
Common prop interfaces used across UI components.
279
280
```typescript { .api }
281
// Permission-based component props
282
interface CheckPermissionsProps {
283
children: React.ReactNode;
284
permissions?: Array<{ action: string; subject: string }>;
285
}
286
287
// Form component props
288
interface FormProps extends Omit<FormikFormProps, 'noValidate'> {
289
children: React.ReactNode;
290
}
291
292
// Generic input props
293
interface GenericInputProps {
294
type: string;
295
name: string;
296
value?: any;
297
onChange?: (event: { target: { name: string; value: any; type: string } }) => void;
298
error?: string | TranslationMessage;
299
description?: string | TranslationMessage;
300
disabled?: boolean;
301
intlLabel?: TranslationMessage;
302
placeholder?: string | TranslationMessage;
303
required?: boolean;
304
step?: number;
305
max?: number;
306
min?: number;
307
attribute?: any;
308
}
309
310
// Table component props
311
interface TableProps<TRows extends { id: Entity.ID } = { id: Entity.ID }> {
312
children?: React.ReactNode;
313
contentType: string;
314
headers?: Array<TableHeader>;
315
rows?: Array<TRows>;
316
isLoading?: boolean;
317
withBulkActions?: boolean;
318
withMainAction?: boolean;
319
onConfirmDeleteAll?: (ids: Array<TRows['id']>) => Promise<void>;
320
onConfirmDelete?: (id: TRows['id']) => Promise<void>;
321
footer?: React.ReactNode;
322
action?: React.ReactNode;
323
}
324
325
// Table header definition
326
interface TableHeader {
327
name: string;
328
metadatas: {
329
sortable: boolean;
330
label: string;
331
mainField?: { name: string };
332
};
333
fieldSchema?: { type: string };
334
}
335
```
336
337
**Usage Examples:**
338
339
```typescript
340
// Type-safe component props
341
const MyFormComponent: React.FC<FormProps> = ({ children, ...props }) => {
342
return <Form {...props}>{children}</Form>;
343
};
344
345
// Table with typed rows
346
interface Article {
347
id: number;
348
title: string;
349
status: 'draft' | 'published';
350
}
351
352
const ArticleTable: React.FC = () => {
353
const tableProps: TableProps<Article> = {
354
contentType: 'articles',
355
headers: [
356
{ name: 'title', metadatas: { label: 'Title', sortable: true } },
357
{ name: 'status', metadatas: { label: 'Status', sortable: false } }
358
],
359
rows: articles,
360
withBulkActions: true,
361
onConfirmDelete: handleDelete
362
};
363
364
return <DynamicTable {...tableProps} />;
365
};
366
```
367
368
## Hook Return Types
369
370
Types for values returned by custom hooks.
371
372
```typescript { .api }
373
// Fetch client hook return
374
interface FetchClientReturn {
375
get: <TData = any>(url: string, config?: any) => Promise<TData>;
376
post: <TData = any, TResponse = any>(url: string, data?: any, config?: any) => Promise<TResponse>;
377
put: <TData = any>(url: string, data?: any, config?: any) => Promise<TData>;
378
del: <TData = any>(url: string, config?: any) => Promise<TData>;
379
}
380
381
// RBAC hook return
382
interface AllowedActions {
383
[key: string]: boolean;
384
}
385
386
interface RBACReturn {
387
allowedActions: AllowedActions;
388
isLoading: boolean;
389
setIsLoading: () => void;
390
}
391
392
// Selection state hook return
393
interface SelectionActions<TValues> {
394
selectOne: (selection: TValues) => void;
395
selectAll: (nextSelections: TValues[]) => void;
396
selectOnly: (nextSelection: TValues) => void;
397
selectMultiple: (nextSelections: TValues[]) => void;
398
deselectMultiple: (nextSelections: TValues[]) => void;
399
setSelections: (selections: TValues[]) => void;
400
}
401
402
type UseSelectionStateReturn<TValues> = readonly [TValues[], SelectionActions<TValues>];
403
404
// Clipboard hook return
405
interface ClipboardReturn {
406
copy: (value: string | number) => Promise<boolean>;
407
}
408
409
// Query params hook return
410
interface QueryResult<TQuery> {
411
query: TQuery;
412
rawQuery: string;
413
}
414
415
type UseQueryParamsReturn<TQuery> = readonly [
416
QueryResult<TQuery>,
417
(nextParams: TQuery, method?: 'push' | 'remove') => void
418
];
419
```
420
421
**Usage Examples:**
422
423
```typescript
424
// Use typed hook returns
425
const { allowedActions, isLoading }: RBACReturn = useRBAC({
426
create: [{ action: 'create', subject: 'api::article.article' }]
427
});
428
429
// Selection state with typed values
430
interface SelectableItem {
431
id: number;
432
name: string;
433
}
434
435
const [selections, actions]: UseSelectionStateReturn<SelectableItem> = useSelectionState(
436
['id'],
437
[]
438
);
439
440
// Type-safe query parameters
441
interface QueryParams {
442
search?: string;
443
page?: number;
444
sort?: string;
445
}
446
447
const [{ query }, setQuery]: UseQueryParamsReturn<QueryParams> = useQueryParams({
448
page: 1,
449
sort: 'name:asc'
450
});
451
```
452
453
## Context Value Types
454
455
Types for React context values used throughout the plugin system.
456
457
```typescript { .api }
458
// App information context
459
interface AppInfoContextValue {
460
autoReload?: boolean;
461
communityEdition?: boolean;
462
currentEnvironment?: string;
463
dependencies?: Record<string, string>;
464
latestStrapiReleaseTag?: string;
465
nodeVersion?: string;
466
projectId?: string | null;
467
setUserDisplayName: (name: string) => void;
468
shouldUpdateStrapi: boolean;
469
strapiVersion?: string | null;
470
useYarn?: boolean;
471
userDisplayName: string;
472
userId?: string;
473
}
474
475
// Notification context
476
interface NotificationConfig {
477
blockTransition?: boolean;
478
link?: NotificationLink;
479
message?: string | TranslationMessage;
480
onClose?: () => void;
481
timeout?: number;
482
title?: string | TranslationMessage;
483
type?: 'info' | 'warning' | 'softWarning' | 'success';
484
}
485
486
interface NotificationsContextValue {
487
toggleNotification: (config: NotificationConfig) => void;
488
}
489
490
// RBAC context
491
interface Permission {
492
id?: Entity.ID;
493
action: string;
494
actionParameters?: object;
495
subject?: string | null;
496
properties?: {
497
fields?: string[];
498
locales?: string[];
499
[key: string]: any;
500
};
501
conditions?: string[];
502
}
503
504
interface RBACContextValue {
505
allPermissions: Permission[];
506
refetchPermissions: () => void;
507
}
508
509
// Tracking context
510
interface TrackingContextValue {
511
uuid?: string | boolean;
512
deviceId?: string;
513
telemetryProperties?: TelemetryProperties;
514
}
515
516
interface TelemetryProperties {
517
useTypescriptOnServer?: boolean;
518
useTypescriptOnAdmin?: boolean;
519
isHostedOnStrapiCloud?: boolean;
520
numberOfAllContentTypes?: number;
521
numberOfComponents?: number;
522
numberOfDynamicZones?: number;
523
}
524
```
525
526
**Usage Examples:**
527
528
```typescript
529
// Create typed context providers
530
const MyCustomProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
531
const appInfo: AppInfoContextValue = useAppInfo();
532
const { toggleNotification }: NotificationsContextValue = useNotification();
533
534
const handleAction = () => {
535
if (appInfo.shouldUpdateStrapi) {
536
toggleNotification({
537
type: 'info',
538
message: 'Update available!'
539
});
540
}
541
};
542
543
return (
544
<div>
545
{children}
546
<button onClick={handleAction}>Check Updates</button>
547
</div>
548
);
549
};
550
```
551
552
## Utility Function Types
553
554
Types for parameters and return values of utility functions.
555
556
```typescript { .api }
557
// HTTP client configuration
558
interface FetchClientOptions extends AxiosRequestConfig {
559
signal?: AbortSignal;
560
}
561
562
// Error normalization options
563
interface NormalizeErrorOptions {
564
name?: string;
565
intlMessagePrefixCallback?: (id: string) => string;
566
}
567
568
// Permission checking types
569
type PermissionToCheckAgainst = Pick<Permission, 'action' | 'subject'> &
570
Partial<Pick<Permission, 'actionParameters' | 'conditions' | 'properties'>>;
571
572
// Storage types
573
interface StorageItems {
574
userInfo: UserInfo;
575
jwtToken: string;
576
STRAPI_THEME: 'light' | 'dark';
577
GUIDED_TOUR_CURRENT_STEP: string | null;
578
GUIDED_TOUR_COMPLETED_STEPS: string[] | null;
579
GUIDED_TOUR_SKIPPED: boolean | null;
580
STRAPI_UPDATE_NOTIF: boolean | null;
581
STRAPI_UPLOAD_MODAL_VIEW: 0 | 1 | null;
582
STRAPI_UPLOAD_LIBRARY_VIEW: 0 | 1 | null;
583
videos: unknown;
584
onboarding: unknown;
585
}
586
587
type StorageItemValues = StorageItems[keyof StorageItems];
588
```
589
590
## Event & Tracking Types
591
592
Comprehensive type system for analytics and event tracking.
593
594
```typescript { .api }
595
// Base event without properties
596
interface EventWithoutProperties {
597
name: 'didCreateEntry' | 'didDeleteEntry' | 'didEditEntry' | /* ... many more */;
598
properties?: never;
599
}
600
601
// Events with specific properties
602
interface CreateEntryEvents {
603
name: 'willCreateEntry' | 'didCreateEntry' | 'didNotCreateEntry';
604
properties: {
605
status?: string;
606
error?: unknown;
607
};
608
}
609
610
interface NavigationEvent {
611
name: 'willNavigate';
612
properties: {
613
from: string;
614
to: string;
615
};
616
}
617
618
// Union of all tracking events
619
type TrackingEvent = EventWithoutProperties | CreateEntryEvents | NavigationEvent | /* ... others */;
620
621
// Tracking hook interface
622
interface UseTrackingReturn {
623
trackUsage<TEvent extends TrackingEvent>(
624
event: TEvent['name'],
625
properties?: TEvent['properties']
626
): Promise<null | AxiosResponse<string>>;
627
}
628
```
629
630
**Usage Examples:**
631
632
```typescript
633
// Type-safe event tracking
634
const { trackUsage }: UseTrackingReturn = useTracking();
635
636
// Events without properties
637
trackUsage('didCreateEntry');
638
639
// Events with properties
640
trackUsage('willNavigate', {
641
from: '/admin/plugins',
642
to: '/admin/content-manager'
643
});
644
645
trackUsage('didCreateEntry', {
646
status: 'success'
647
});
648
```
649
650
## Generic & Utility Types
651
652
Helper types for generic operations and type transformations.
653
654
```typescript { .api }
655
// Make all properties of an object non-nullable
656
type NonNullableObject<T> = {
657
[K in keyof T]: NonNullable<T[K]>;
658
};
659
660
// Empty object type
661
type EmptyObject = Record<string, never>;
662
663
// Callback ref type
664
type CallbackRef<T> = (instance: T | null) => void;
665
666
// Axios response wrapper
667
interface AxiosResponseWrapper<T> extends AxiosResponse<T> {
668
data: T;
669
}
670
671
// Generic ID types
672
type EntityID = string | number;
673
674
// Generic entity with ID
675
interface WithId {
676
id: EntityID;
677
}
678
679
// Partial with required ID
680
type PartialWithId<T> = Partial<T> & WithId;
681
```
682
683
**Usage Examples:**
684
685
```typescript
686
// Use generic types for type safety
687
interface MyEntity {
688
id: number;
689
name: string;
690
description?: string;
691
}
692
693
// Ensure all properties are non-null
694
type RequiredEntity = NonNullableObject<MyEntity>;
695
696
// Create partial updates with required ID
697
type EntityUpdate = PartialWithId<MyEntity>;
698
699
const updateEntity = (update: EntityUpdate) => {
700
// update.id is guaranteed to exist
701
// other properties are optional
702
console.log(`Updating entity ${update.id}`);
703
};
704
```
705
706
## Type Integration Best Practices
707
708
### Component Type Safety
709
710
```typescript
711
// Extend base props with additional types
712
interface MyComponentProps extends GenericInputProps {
713
customOption?: boolean;
714
onCustomEvent?: () => void;
715
}
716
717
const MyComponent: React.FC<MyComponentProps> = (props) => {
718
return <GenericInput {...props} />;
719
};
720
```
721
722
### API Response Typing
723
724
```typescript
725
// Define API response shapes
726
interface ArticleListResponse {
727
data: ContentType[];
728
meta: {
729
pagination: {
730
page: number;
731
pageSize: number;
732
pageCount: number;
733
total: number;
734
};
735
};
736
}
737
738
// Use with fetch client
739
const { get }: FetchClientReturn = useFetchClient();
740
const response = await get<ArticleListResponse>('/api/articles');
741
```
742
743
### Error Handling with Types
744
745
```typescript
746
// Create typed error handlers
747
const handleTypedError = (error: unknown) => {
748
if (error && typeof error === 'object' && 'response' in error) {
749
const axiosError = error as AxiosError<{ error: ApiError }>;
750
const normalized = normalizeAPIError(axiosError);
751
752
if (normalized) {
753
console.error(normalized.defaultMessage);
754
}
755
}
756
};
757
```
758
759
The comprehensive type system in @strapi/helper-plugin ensures type safety across all plugin development scenarios, from UI components to API interactions to data management operations.