0
# Type System Conversion
1
2
Comprehensive type conversion system that transforms docgen type information between different type system representations including PropTypes, Flow, and TypeScript.
3
4
## Capabilities
5
6
### Universal Type Conversion
7
8
Main conversion function that handles type information from any supported type system.
9
10
```typescript { .api }
11
/**
12
* Converts docgen type information to Storybook-compatible format
13
* @param docgenInfo - Type information from docgen tools
14
* @returns Converted type information or null if conversion fails
15
*/
16
function convert(docgenInfo: DocgenInfo): any | null;
17
18
interface DocgenInfo {
19
/** PropTypes type information */
20
type: DocgenPropType;
21
/** Flow type information (optional) */
22
flowType?: DocgenFlowType;
23
/** TypeScript type information (optional) */
24
tsType?: DocgenTypeScriptType;
25
/** Whether the property is required */
26
required: boolean;
27
/** Property description */
28
description: string;
29
/** Default value information */
30
defaultValue: DocgenPropDefaultValue;
31
}
32
```
33
34
The conversion function automatically detects the available type system and applies the appropriate conversion logic, with graceful fallback handling.
35
36
**Usage Examples:**
37
38
```typescript
39
import { convert } from "@storybook/docs-tools";
40
41
// Convert TypeScript type information
42
const tsDocgenInfo = {
43
type: null,
44
tsType: {
45
name: 'string | number',
46
raw: 'string | number'
47
},
48
required: true,
49
description: 'Input value',
50
defaultValue: { value: '""' }
51
};
52
53
const convertedType = convert(tsDocgenInfo);
54
console.log(convertedType);
55
// { summary: 'string | number', detail: 'string | number' }
56
57
// Convert PropTypes information
58
const propTypesInfo = {
59
type: {
60
name: 'union',
61
value: [
62
{ name: 'string' },
63
{ name: 'number' }
64
]
65
},
66
required: false,
67
description: 'Value can be string or number',
68
defaultValue: { value: 'null' }
69
};
70
71
const propTypesConverted = convert(propTypesInfo);
72
73
// Convert Flow type information
74
const flowInfo = {
75
type: null,
76
flowType: {
77
name: 'Array',
78
elements: [{ name: 'string' }],
79
raw: 'Array<string>'
80
},
81
required: true,
82
description: 'Array of strings',
83
defaultValue: { value: '[]' }
84
};
85
86
const flowConverted = convert(flowInfo);
87
88
// Handle conversion failures gracefully
89
function safeConvert(docgenInfo: DocgenInfo) {
90
try {
91
const result = convert(docgenInfo);
92
return result || { summary: 'unknown' };
93
} catch (error) {
94
console.warn('Type conversion failed:', error);
95
return { summary: 'any' };
96
}
97
}
98
```
99
100
### Type System Enumeration
101
102
Enumeration defining the supported type systems for component analysis.
103
104
```typescript { .api }
105
/**
106
* Supported type systems for component documentation
107
*/
108
enum TypeSystem {
109
/** Standard JavaScript with PropTypes */
110
JAVASCRIPT = "JavaScript",
111
/** Flow static type checker */
112
FLOW = "Flow",
113
/** TypeScript static type system */
114
TYPESCRIPT = "TypeScript",
115
/** Unable to determine type system */
116
UNKNOWN = "Unknown"
117
}
118
```
119
120
**Usage Examples:**
121
122
```typescript
123
import { TypeSystem } from "@storybook/docs-tools";
124
125
// Type system detection
126
function detectComponentTypeSystem(component: any): TypeSystem {
127
if (component.__docgenInfo?.props) {
128
const firstProp = Object.values(component.__docgenInfo.props)[0] as any;
129
130
if (firstProp?.tsType) {
131
return TypeSystem.TYPESCRIPT;
132
}
133
134
if (firstProp?.flowType) {
135
return TypeSystem.FLOW;
136
}
137
138
if (firstProp?.type) {
139
return TypeSystem.JAVASCRIPT;
140
}
141
}
142
143
return TypeSystem.UNKNOWN;
144
}
145
146
// Framework-specific handling
147
function processComponentByTypeSystem(component: any, typeSystem: TypeSystem) {
148
switch (typeSystem) {
149
case TypeSystem.TYPESCRIPT:
150
return processTypeScriptComponent(component);
151
case TypeSystem.FLOW:
152
return processFlowComponent(component);
153
case TypeSystem.JAVASCRIPT:
154
return processJavaScriptComponent(component);
155
default:
156
return processGenericComponent(component);
157
}
158
}
159
```
160
161
### DocGen Type Interfaces
162
163
Detailed interfaces that define the structure of type information from different docgen tools.
164
165
```typescript { .api }
166
interface DocgenType {
167
/** Type name */
168
name: string;
169
/** Type description */
170
description?: string;
171
/** Whether the type is required */
172
required?: boolean;
173
/** Type value information */
174
value?: any;
175
}
176
177
interface DocgenPropType extends DocgenType {
178
/** Type value (varies by type) */
179
value?: any;
180
/** Raw type string */
181
raw?: string;
182
/** Whether type is computed */
183
computed?: boolean;
184
}
185
186
interface DocgenFlowType extends DocgenType {
187
/** Flow type category */
188
type?: string;
189
/** Raw Flow type string */
190
raw?: string;
191
/** Function signature information */
192
signature?: any;
193
/** Array/object element types */
194
elements?: any[];
195
}
196
197
interface DocgenTypeScriptType extends DocgenType {
198
/** Raw TypeScript type string */
199
raw?: string;
200
}
201
202
interface DocgenPropDefaultValue {
203
/** Default value as string */
204
value: string;
205
/** Whether value is computed */
206
computed?: boolean;
207
/** Whether value is a function */
208
func?: boolean;
209
}
210
```
211
212
**Usage Examples:**
213
214
```typescript
215
// Process different type formats
216
function processDocgenType(docgenInfo: DocgenInfo) {
217
// Handle TypeScript types
218
if (docgenInfo.tsType) {
219
const tsType: DocgenTypeScriptType = docgenInfo.tsType;
220
console.log(`TS Type: ${tsType.name} (${tsType.raw})`);
221
}
222
223
// Handle Flow types
224
if (docgenInfo.flowType) {
225
const flowType: DocgenFlowType = docgenInfo.flowType;
226
console.log(`Flow Type: ${flowType.name}`);
227
228
if (flowType.elements) {
229
console.log('Element types:', flowType.elements);
230
}
231
}
232
233
// Handle PropTypes
234
if (docgenInfo.type) {
235
const propType: DocgenPropType = docgenInfo.type;
236
console.log(`PropType: ${propType.name}`);
237
238
if (propType.value) {
239
console.log('Type value:', propType.value);
240
}
241
}
242
243
// Process default values
244
if (docgenInfo.defaultValue) {
245
const defaultVal = docgenInfo.defaultValue;
246
console.log(`Default: ${defaultVal.value} (computed: ${defaultVal.computed})`);
247
}
248
}
249
```
250
251
### PropDef Factory Functions
252
253
Specialized factory functions for creating PropDef objects from different type systems.
254
255
```typescript { .api }
256
/**
257
* Creates PropDef for JavaScript/PropTypes components
258
* @param propName - Name of the property
259
* @param docgenInfo - Docgen information for the prop
260
* @param jsDocTags - Optional JSDoc tag information
261
* @returns PropDef object for JavaScript component
262
*/
263
const javaScriptFactory: PropDefFactory;
264
265
/**
266
* Creates PropDef for TypeScript components
267
* @param propName - Name of the property
268
* @param docgenInfo - Docgen information for the prop
269
* @param jsDocTags - Optional JSDoc tag information
270
* @returns PropDef object for TypeScript component with TS type information
271
*/
272
const tsFactory: PropDefFactory;
273
274
/**
275
* Creates PropDef for Flow components
276
* @param propName - Name of the property
277
* @param docgenInfo - Docgen information for the prop
278
* @param jsDocTags - Optional JSDoc tag information
279
* @returns PropDef object for Flow component with Flow type information
280
*/
281
const flowFactory: PropDefFactory;
282
283
/**
284
* Creates PropDef for components with unknown type systems
285
* @param propName - Name of the property
286
* @param docgenInfo - Docgen information for the prop
287
* @param jsDocTags - Optional JSDoc tag information
288
* @returns Basic PropDef object with fallback type information
289
*/
290
const unknownFactory: PropDefFactory;
291
292
/**
293
* Gets the appropriate PropDef factory based on type system
294
* @param typeSystem - Detected or specified type system
295
* @returns Factory function for the given type system
296
*/
297
function getPropDefFactory(typeSystem: TypeSystem): PropDefFactory;
298
299
/**
300
* Creates PropDef for Flow type components (alias for flowFactory)
301
* @param propName - Name of the property
302
* @param docgenInfo - Docgen information for the prop
303
* @param jsDocTags - Optional JSDoc tag information
304
* @returns PropDef object for Flow component
305
*/
306
const createFlowPropDef: PropDefFactory;
307
308
/**
309
* Creates PropDef for TypeScript components (alias for tsFactory)
310
* @param propName - Name of the property
311
* @param docgenInfo - Docgen information for the prop
312
* @param jsDocTags - Optional JSDoc tag information
313
* @returns PropDef object for TypeScript component
314
*/
315
const createTsPropDef: PropDefFactory;
316
```
317
318
**Usage Examples:**
319
320
```typescript
321
import {
322
getPropDefFactory,
323
javaScriptFactory,
324
tsFactory,
325
flowFactory,
326
TypeSystem
327
} from "@storybook/docs-tools";
328
329
// Using factory selection
330
function createPropDef(propName: string, docgenInfo: DocgenInfo, typeSystem: TypeSystem) {
331
const factory = getPropDefFactory(typeSystem);
332
return factory(propName, docgenInfo);
333
}
334
335
// Direct factory usage
336
const tsDocgenInfo = {
337
type: { name: 'string' },
338
tsType: { name: 'string', raw: 'string' },
339
required: true,
340
description: 'User name input',
341
defaultValue: { value: '""', computed: false }
342
};
343
344
const tsPropDef = tsFactory('userName', tsDocgenInfo);
345
console.log(tsPropDef);
346
// {
347
// name: 'userName',
348
// type: { summary: 'string' },
349
// required: true,
350
// description: 'User name input',
351
// defaultValue: { summary: '""' }
352
// }
353
354
// Flow factory usage
355
const flowDocgenInfo = {
356
type: { name: 'number' },
357
flowType: { name: 'number', raw: 'number' },
358
required: false,
359
description: 'Item count',
360
defaultValue: { value: '0', computed: false }
361
};
362
363
const flowPropDef = flowFactory('count', flowDocgenInfo);
364
365
// JavaScript/PropTypes factory usage
366
const jsDocgenInfo = {
367
type: {
368
name: 'union',
369
value: [{ name: 'string' }, { name: 'number' }]
370
},
371
required: true,
372
description: 'Mixed type value',
373
defaultValue: null
374
};
375
376
const jsPropDef = javaScriptFactory('mixedValue', jsDocgenInfo);
377
378
// Framework integration
379
function processFrameworkComponent(component: any, framework: string) {
380
const props = component.__docgenInfo?.props || {};
381
const typeSystem = detectTypeSystemFromFramework(framework);
382
const factory = getPropDefFactory(typeSystem);
383
384
return Object.entries(props).map(([propName, propInfo]) => {
385
return factory(propName, propInfo as DocgenInfo);
386
});
387
}
388
389
// Type system detection helper
390
function detectTypeSystemFromFramework(framework: string): TypeSystem {
391
switch (framework) {
392
case 'react-ts':
393
case 'vue-ts':
394
return TypeSystem.TYPESCRIPT;
395
case 'react-flow':
396
return TypeSystem.FLOW;
397
case 'react':
398
case 'vue':
399
default:
400
return TypeSystem.JAVASCRIPT;
401
}
402
}
403
```
404
405
### Conversion System Architecture
406
407
The conversion system uses specialized converters for each type system with shared utilities.
408
409
```typescript
410
// Type-specific conversion functions (internal)
411
interface TypeConverter {
412
convert(typeInfo: any): { summary: string; detail?: string } | null;
413
}
414
415
// Example usage patterns
416
const processConversionResult = (result: any) => {
417
if (!result) {
418
return { summary: 'unknown' };
419
}
420
421
return {
422
summary: result.summary || 'any',
423
detail: result.detail
424
};
425
};
426
427
// Framework integration
428
function createTypeConverter(framework: string) {
429
return (docgenInfo: DocgenInfo) => {
430
const converted = convert(docgenInfo);
431
432
if (!converted) {
433
// Framework-specific fallback
434
return getFrameworkFallbackType(framework);
435
}
436
437
return converted;
438
};
439
}
440
```
441
442
### Complex Type Handling
443
444
The conversion system handles complex type structures including unions, intersections, generics, and nested objects.
445
446
```typescript
447
// Example complex type conversions
448
const complexTypes = {
449
// Union types
450
stringOrNumber: {
451
type: {
452
name: 'union',
453
value: [{ name: 'string' }, { name: 'number' }]
454
}
455
},
456
457
// Generic types
458
arrayOfStrings: {
459
tsType: {
460
name: 'Array<string>',
461
raw: 'Array<string>'
462
}
463
},
464
465
// Object types
466
configObject: {
467
type: {
468
name: 'shape',
469
value: {
470
enabled: { name: 'bool' },
471
count: { name: 'number' }
472
}
473
}
474
},
475
476
// Function types
477
eventHandler: {
478
type: {
479
name: 'func',
480
signature: {
481
arguments: [{ name: 'event' }],
482
return: { name: 'void' }
483
}
484
}
485
}
486
};
487
488
// Process complex types
489
Object.entries(complexTypes).forEach(([name, docgenInfo]) => {
490
const converted = convert(docgenInfo as DocgenInfo);
491
console.log(`${name}:`, converted);
492
});
493
```