Juris Types Developer Guide - jurisjs/juris GitHub Wiki

A comprehensive guide to building type-safe applications with the Juris framework, featuring advanced TypeScript definitions, component validation, and enterprise-grade developer experience.


🎯 Introduction

The Juris Types system provides framework-aware TypeScript definitions that understand how Juris works internally. Unlike generic TypeScript, these types know about:

  • VDOM structure and element properties
  • Reactive patterns and async handling
  • Component lifecycle and props
  • State management with dot notation
  • Event handling with proper signatures

Why Juris Types?

// ❌ Regular JavaScript - Runtime errors
{
  dvi: { className: 'typo' },        // Silent failure
  UserCard: { invalidProp: true },   // Runtime error
  children: [42, null, undefined]    // Broken rendering
}

// ✅ With Juris Types - Caught immediately
{
  div: { className: 'correct' },     // ✅ Valid HTML element
  UserCard: { props: { user } },     // ✅ Typed component props
  children: [{ p: { text: 'Hi' } }]  // ✅ Valid VDOM elements
}

⚡ Quick Setup

1. Install Type Definitions

# Copy the types folder to your project
types/
├── index.d.ts      # Core Juris types
├── index.js        # JavaScript IntelliSense
├── app.d.ts        # Your app-specific types
└── html-helper.js  # Types for inline scripts

2. Configure Your IDE

VS Code (jsconfig.json):

{
  "compilerOptions": {
    "checkJs": true,
    "allowJs": true,
    "baseUrl": ".",
    "paths": {
      "@types": ["./types/index.d.ts"]
    }
  },
  "include": ["**/*.js", "**/*.d.ts"]
}

3. Basic Component Template

/**
 * @param {{
 *   // Define your props here
 * }} props
 * @param {import('@types').JurisContext} context
 * @returns {import('@types').JurisVDOMElement}
 */
export const MyComponent = (props, context) => {
    // Full type safety and IntelliSense here!
    return {
        div: {
            text: 'Hello, Juris Types!'
        }
    };
};

🔧 Core Concepts

Type Safety Levels

Juris Types provides 3 levels of type safety:

  1. HTML Elements - Strict validation of HTML tags and properties
  2. Registered Components - Type-safe custom components
  3. Framework APIs - Context, state, and lifecycle methods

Element vs Component

// HTML Element (built-in)
{
  div: {              // ✅ Known HTML element
    className: 'box',  // ✅ Valid HTML property
    onClick: () => {}  // ✅ Valid event handler
  }
}

// Custom Component (registered)
{
  UserCard: {          // ✅ Registered component
    props: {           // ✅ Component props
      user: userData   // ✅ Typed prop
    }
  }
}

// Invalid Examples
{
  dvi: {},            // ❌ Typo in HTML element
  UnknownComp: {},    // ❌ Unregistered component
  div: { badProp: 1 } // ❌ Invalid HTML property
}

The Component Registry

All custom components must be registered in types/app.d.ts:

declare global {
  namespace Juris {
    interface RegisteredComponents {
      ComponentName: {
        props: {
          // Define props and their types
        };
        slots?: {
          // Define slots if component supports them
        };
      };
    }
  }
}

📝 Component Typing

Basic Component Definition

/**
 * @param {{
 *   title: string,
 *   count?: number,
 *   items: Array<{id: string, name: string}>,
 *   onItemClick?: (item: any) => void,
 *   disabled?: boolean
 * }} props
 * @param {import('@types').JurisContext} context
 * @returns {import('@types').JurisVDOMElement}
 */
export const ItemList = (props, context) => {
    const { title, count = 0, items, onItemClick, disabled = false } = props;
    const { getState, setState } = context;
    
    return {
        div: {
            className: 'item-list',
            children: [
                { h2: { text: title } },
                { p: { text: `Total: ${count}` } },
                {
                    ul: {
                        children: items.map(item => ({
                            li: {
                                text: item.name,
                                onClick: disabled ? undefined : () => onItemClick?.(item)
                            }
                        }))
                    }
                }
            ]
        }
    };
};

Register Component Type

// types/app.d.ts
declare global {
  namespace Juris {
    interface RegisteredComponents {
      ItemList: {
        props: {
          title: string;
          count?: number;
          items: Array<{id: string, name: string}>;
          onItemClick?: (item: {id: string, name: string}) => void;
          disabled?: boolean;
        };
      };
    }
  }
}

Advanced Component Patterns

Generic Component

/**
 * @template T
 * @param {{
 *   items: T[],
 *   renderItem: (item: T, index: number) => import('@types').JurisVDOMElement,
 *   keyExtractor?: (item: T) => string,
 *   loading?: boolean,
 *   emptyMessage?: string
 * }} props
 * @param {import('@types').JurisContext} context
 * @returns {import('@types').JurisVDOMElement}
 */
export const GenericList = (props, context) => {
    const { items, renderItem, keyExtractor, loading, emptyMessage } = props;
    
    if (loading) {
        return { div: { className: 'loading', text: 'Loading...' } };
    }
    
    if (items.length === 0) {
        return { div: { className: 'empty', text: emptyMessage || 'No items' } };
    }
    
    return {
        div: {
            className: 'generic-list',
            children: items.map((item, index) => {
                const key = keyExtractor ? keyExtractor(item) : index.toString();
                return {
                    div: {
                        key,
                        children: [renderItem(item, index)]
                    }
                };
            })
        }
    };
};

Component with Slots

/**
 * @param {{
 *   title: string,
 *   isOpen: boolean,
 *   size?: 'small' | 'medium' | 'large',
 *   onClose?: () => void
 * }} props
 * @param {import('@types').JurisContext} context
 * @returns {import('@types').JurisVDOMElement}
 */
export const Modal = (props, context) => {
    const { title, isOpen, size = 'medium', onClose } = props;
    
    if (!isOpen) return null;
    
    return {
        div: {
            className: `modal modal-${size}`,
            children: [
                {
                    div: {
                        className: 'modal-header',
                        children: [
                            { h3: { text: title } },
                            onClose ? {
                                button: {
                                    className: 'modal-close',
                                    text: '×',
                                    onClick: onClose
                                }
                            } : null
                        ].filter(Boolean)
                    }
                },
                {
                    div: {
                        className: 'modal-body',
                        children: [] // Will be populated by slots
                    }
                }
            ]
        }
    };
};

Register with slots:

Modal: {
  props: {
    title: string;
    isOpen: boolean;
    size?: 'small' | 'medium' | 'large';
    onClose?: () => void;
  };
  slots?: {
    body?: JurisVDOMElement[];
    footer?: JurisVDOMElement[];
  };
};

🎨 VDOM Element Types

HTML Element Categories

Text Elements

// Elements that primarily contain text
{ h1: { text: 'Heading' } }
{ p: { text: 'Paragraph content' } }
{ span: { text: 'Inline text' } }
{ label: { text: 'Form label' } }

Container Elements

// Elements that contain other elements
{
  div: {
    className: 'container',
    children: [
      { p: { text: 'Child paragraph' } },
      { span: { text: 'Child span' } }
    ]
  }
}

Form Elements

{
  input: {
    type: 'text',
    value: () => getState('inputValue', ''),
    placeholder: 'Enter text...',
    onChange: (e) => setState('inputValue', e.target.value)
  }
}

{
  select: {
    value: () => getState('selectedValue'),
    onChange: (e) => setState('selectedValue', e.target.value),
    children: [
      { option: { value: 'a', text: 'Option A' } },
      { option: { value: 'b', text: 'Option B' } }
    ]
  }
}

Media Elements

{
  img: {
    src: 'image.jpg',
    alt: 'Description',
    width: 200,
    height: 150,
    onLoad: () => console.log('Image loaded')
  }
}

{
  video: {
    src: 'video.mp4',
    controls: true,
    autoplay: false,
    onPlay: () => setState('videoPlaying', true)
  }
}

Mixed Content Elements

Some elements can have either text OR children:

// Text content
{ div: { text: 'Simple text' } }

// Child elements
{
  div: {
    children: [
      { p: { text: 'Paragraph' } },
      { span: { text: 'Span' } }
    ]
  }
}

// ❌ Don't mix them
{
  div: {
    text: 'Text',
    children: [...] // This will be ignored
  }
}

Element Properties

Common Properties

{
  div: {
    // Identification
    id: 'unique-id',
    className: 'css-classes',
    
    // Accessibility
    'aria-label': 'Screen reader text',
    'aria-hidden': false,
    role: 'button',
    tabIndex: 0,
    
    // Data attributes
    'data-testid': 'test-identifier',
    'data-value': 'custom-data',
    
    // Styling
    style: {
      color: 'red',
      backgroundColor: 'blue',
      padding: '10px'
    },
    
    // Events (see Event Handling section)
    onClick: (e) => {},
    onMouseOver: (e) => {}
  }
}

🔄 Reactive Values

Juris supports reactive patterns where any property can be static, a function, or a Promise.

Static Values

{
  div: {
    className: 'static-class',
    text: 'Static text',
    style: { color: 'red' }
  }
}

Reactive Functions

{
  div: {
    className: () => getState('theme') === 'dark' ? 'dark-mode' : 'light-mode',
    text: () => `Count: ${getState('counter', 0)}`,
    style: () => ({
      opacity: getState('visible', true) ? 1 : 0
    })
  }
}

Async Promises

{
  div: {
    text: fetchUserName(userId), // Returns Promise<string>
    children: loadMenuItems(),    // Returns Promise<Element[]>
    style: computeStyles()        // Returns Promise<CSSStyleDeclaration>
  }
}

Reactive Children

Children can be static, reactive, or async:

{
  div: {
    // Static children
    children: [
      { p: { text: 'Always visible' } }
    ]
  }
}

{
  div: {
    // Reactive children
    children: () => {
      const items = getState('items', []);
      return items.map(item => ({
        div: { text: item.name }
      }));
    }
  }
}

{
  div: {
    // Async children
    children: async () => {
      const data = await fetchData();
      return data.map(item => ({
        div: { text: item.title }
      }));
    }
  }
}

Type Safety with Reactive Values

The type system ensures reactive values return the correct types:

{
  div: {
    // ✅ These are all valid:
    text: 'static string',
    text: () => 'function returning string',
    text: Promise.resolve('promise of string'),
    
    // ❌ These will show errors:
    text: () => 42,              // Error: number not assignable to string
    text: Promise.resolve(true), // Error: boolean not assignable to string
    
    children: [{ p: { text: 'valid' } }],           // ✅ Valid element array
    children: () => [{ p: { text: 'valid' } }],     // ✅ Function returning elements
    children: () => [{ badElement: {} }],           // ❌ Error: invalid element
  }
}

🚦 Error Detection

The Juris type system catches errors at multiple levels and provides specific error messages.

HTML Element Typos

// ❌ Typos in HTML elements
{
  dvi: { className: 'container' }    // Error: Property 'dvi' does not exist
}
{
  buton: { text: 'Click' }           // Error: Property 'buton' does not exist  
}

// ✅ Correct spelling
{
  div: { className: 'container' }    // ✅ Valid
}
{
  button: { text: 'Click' }          // ✅ Valid
}

Component Registration Errors

// ❌ Unregistered component
{
  UnknownComponent: {               // Error: Component 'UnknownComponent' not registered
    props: { data: 'test' }
  }
}

// ✅ After registering in app.d.ts
{
  KnownComponent: {                 // ✅ Valid registered component
    props: { data: 'test' }
  }
}

Property Type Errors

{
  div: {
    // ❌ Wrong types
    className: 123,                 // Error: number not assignable to string
    onClick: 'not a function',      // Error: string not assignable to function
    
    // ✅ Correct types  
    className: 'valid-class',       // ✅ String
    onClick: () => console.log()    // ✅ Function
  }
}

Children Array Errors

{
  div: {
    children: [
      { p: { text: 'Valid paragraph' } },      // ✅ Valid element
      { invalidElement: {} },                  // ❌ Error: invalid element
      'Plain text not allowed',                // ❌ Error: string not element
      42,                                      // ❌ Error: number not element
      null                                     // ❌ Error: null not element
    ]
  }
}

// ✅ Correct children
{
  div: {
    children: [
      { p: { text: 'Valid paragraph' } },
      { span: { text: 'Valid span' } }
    ]
  }
}

Reactive Function Errors

{
  div: {
    // ❌ Function returns wrong type
    text: () => getState('count', 0),         // Error: number not assignable to string
    
    // ✅ Convert to correct type
    text: () => getState('count', 0).toString(), // ✅ String
    
    // ❌ Function returns invalid children
    children: () => [
      { validElement: { text: 'ok' } },       // ✅ Valid
      { invalidElement: {} }                  // ❌ Error: invalid element
    ]
  }
}

Nested Error Detection

The type system validates deeply nested structures:

{
  div: {
    children: [
      {
        section: {
          children: [
            {
              article: {
                children: [
                  { validElement: { text: 'Deep but valid' } },    // ✅ Valid
                  { deepTypo: { text: 'Deep typo' } }              // ❌ Error caught at any depth
                ]
              }
            }
          ]
        }
      }
    ]
  }
}

Error Messages

The system provides helpful error messages:

❌ Component 'UserForm' not registered. Add to app.d.ts RegisteredComponents interface.

Example:
declare global {
  namespace Juris {
    interface RegisteredComponents {
      UserForm: {
        props: {
          // Define your props here
        };
      };
    }
  }
}

🏗️ Advanced Patterns

State Management with Types

Typed State Paths

// Define your app state structure
/**
 * @typedef {{
 *   user: { name: string, email: string, role: 'admin' | 'user' },
 *   ui: { theme: 'light' | 'dark', sidebar: { open: boolean, width: number } },
 *   data: { users: User[], loading: boolean, error: string | null }
 * }} AppState
 */

/**
 * @param {import('@types').JurisContext<AppState>} context 
 */
function useTypedState(context) {
    const { getState, setState } = context;
    
    // Type-safe state access with dot notation
    const userName = getState('user.name', '');           // string
    const isLoading = getState('data.loading', false);    // boolean
    const sidebarOpen = getState('ui.sidebar.open', true); // boolean
    
    // Type-safe state updates
    setState('user.role', 'admin');                       // ✅ Valid role
    setState('ui.theme', 'dark');                         // ✅ Valid theme
    setState('data.error', 'Something went wrong');       // ✅ Valid error
}

State Subscriptions

// Subscribe to state changes with proper typing
const unsubscribe = context.subscribe('user.name', (newName, oldName, path) => {
    console.log(`User name changed from ${oldName} to ${newName}`);
});

// Subscribe to nested paths
const unsubscribeUI = context.subscribe('ui', (newUI, oldUI, path) => {
    console.log('UI state changed:', newUI);
});

// Cleanup subscriptions
unsubscribe();
unsubscribeUI();

Service Integration

// Define typed services
/**
 * @typedef {{
 *   userService: UserService,
 *   apiClient: ApiClient,
 *   authService: AuthService
 * }} AppServices
 */

/**
 * @param {Object} props
 * @param {import('@types').JurisContext & { services: AppServices }} context
 * @returns {import('@types').JurisVDOMElement}
 */
export const UserManager = (props, context) => {
    const { userService, authService } = context.services;
    const { getState, setState } = context;
    
    const loadUsers = async () => {
        setState('users.loading', true);
        try {
            const users = await userService.getAll();
            setState('users.list', users);
        } catch (error) {
            setState('users.error', error.message);
        } finally {
            setState('users.loading', false);
        }
    };
    
    return {
        div: {
            children: [
                {
                    button: {
                        text: 'Load Users',
                        onClick: loadUsers,
                        disabled: () => getState('users.loading', false)
                    }
                }
            ]
        }
    };
};

Headless Components

/**
 * @param {Object} props
 * @param {import('@types').JurisContext} context
 * @returns {{
 *   api: {
 *     loadData: () => Promise<void>,
 *     saveData: (data: any) => Promise<void>,
 *     clearData: () => void
 *   }
 * }}
 */
export const DataManager = (props, context) => {
    const { getState, setState } = context;
    
    return {
        api: {
            async loadData() {
                setState('loading', true);
                try {
                    const response = await fetch('/api/data');
                    const data = await response.json();
                    setState('data', data);
                } finally {
                    setState('loading', false);
                }
            },
            
            async saveData(data) {
                setState('saving', true);
                try {
                    await fetch('/api/data', {
                        method: 'POST',
                        headers: { 'Content-Type': 'application/json' },
                        body: JSON.stringify(data)
                    });
                    setState('data', data);
                } finally {
                    setState('saving', false);
                }
            },
            
            clearData() {
                setState('data', null);
            }
        }
    };
};

// Use in components
export const DataComponent = (props, context) => {
    const dataManager = context.components.getHeadlessAPI('DataManager');
    
    return {
        div: {
            children: [
                {
                    button: {
                        text: 'Load Data',
                        onClick: () => dataManager.loadData()
                    }
                },
                {
                    button: {
                        text: 'Clear Data',
                        onClick: () => dataManager.clearData()
                    }
                }
            ]
        }
    };
};

Component Composition

/**
 * Higher-order component pattern
 * @param {import('@types').JurisComponentFunction} WrappedComponent
 * @returns {import('@types').JurisComponentFunction}
 */
export const withLoading = (WrappedComponent) => {
    return (props, context) => {
        const { getState } = context;
        const isLoading = getState('loading', false);
        
        if (isLoading) {
            return {
                div: {
                    className: 'loading-wrapper',
                    text: 'Loading...'
                }
            };
        }
        
        return WrappedComponent(props, context);
    };
};

// Usage
const LoadingUserCard = withLoading(UserCard);

🎛️ Configuration

IDE Configuration

VS Code Settings

.vscode/settings.json:

{
    "typescript.validate.enable": true,
    "javascript.validate.enable": true,
    "typescript.preferences.checkJs": true,
    "javascript.preferences.checkJs": true,
    "html.validate.scripts": true,
    "typescript.suggest.autoImports": true,
    "typescript.preferences.includePackageJsonAutoImports": "auto"
}

TypeScript Config

jsconfig.json:

{
    "compilerOptions": {
        "target": "ES2020",
        "module": "ES2020",
        "moduleResolution": "node",
        "allowJs": true,
        "checkJs": true,
        "noEmit": true,
        "baseUrl": ".",
        "paths": {
            "@types": ["./types/index.d.ts"],
            "@types/*": ["./types/*"],
            "@components/*": ["./components/*"],
            "@services/*": ["./services/*"]
        },
        "lib": ["ES2020", "DOM", "DOM.Iterable"]
    },
    "include": [
        "**/*.js",
        "**/*.d.ts"
    ],
    "exclude": [
        "node_modules",
        "dist",
        "build"
    ]
}

Type Configuration

Strict Mode

Enable strict type checking:

{
    "compilerOptions": {
        "strict": true,
        "noImplicitAny": true,
        "strictNullChecks": true,
        "strictFunctionTypes": true
    }
}

Relaxed Mode

For gradual adoption:

{
    "compilerOptions": {
        "strict": false,
        "noImplicitAny": false,
        "checkJs": true
    }
}

🐛 Debugging

Common Type Errors

"Property does not exist"

// ❌ Error: Property 'dvi' does not exist in type 'Element'
{ dvi: { text: 'typo' } }

// ✅ Fix: Correct the spelling
{ div: { text: 'correct' } }

"Component not registered"

// ❌ Error: Component 'UserForm' not registered
{ UserForm: { props: {} } }

// ✅ Fix: Add to app.d.ts
declare global {
  namespace Juris {
    interface RegisteredComponents {
      UserForm: { props: {} };
    }
  }
}

"Type not assignable"

// ❌ Error: Type 'number' is not assignable to type 'string'
{ div: { text: () => getState('count', 0) } }

// ✅ Fix: Convert to string
{ div: { text: () => getState('count', 0).toString() } }

Debugging Tools

Type Inspection

// Check what type TypeScript thinks something is
/**
 * @type {import('@types').JurisVDOMElement}
 */
const element = { div: { text: 'test' } };

// Use in hover or go-to-definition
const elementType = /** @type {import('@types').JurisVDOMElement} */ (element);

Component Validation

// Validate component props at runtime
/**
 * @param {any} props
 * @param {string[]} required
 */
function validateProps(props, required) {
    for (const prop of required) {
        if (!(prop in props)) {
            throw new Error(`Missing required prop: ${prop}`);
        }
    }
}

export const ValidatedComponent = (props, context) => {
    validateProps(props, ['title', 'data']);
    // Component implementation...
};

State Type Checking

// Runtime state validation
const validateState = (path, value, expectedType) => {
    if (typeof value !== expectedType) {
        console.warn(`State at '${path}' expected ${expectedType}, got ${typeof value}`);
    }
};

// Use in setState
const typedSetState = (path, value) => {
    // Add runtime validation
    context.setState(path, value);
};

📋 Best Practices

1. Component Organization

File Structure:

components/
├── ui/              # Basic UI components
│   ├── Button.js
│   ├── Input.js
│   └── Modal.js
├── forms/           # Form-specific components
│   ├── UserForm.js
│   └── SearchForm.js
├── data/            # Data display components
│   ├── UserCard.js
│   ├── DataTable.js
│   └── Chart.js
└── layout/          # Layout components
    ├── Header.js
    ├── Sidebar.js
    └── Footer.js

Naming Conventions:

  • Components: PascalCase (e.g., UserCard, DataTable)
  • Props: camelCase (e.g., isVisible, onItemClick)
  • Event handlers: on prefix (e.g., onClick, onSubmit)

2. Type Definitions

Component Props:

// ✅ Good: Specific types
props: {
  status: 'pending' | 'approved' | 'rejected';
  count: number;
  onUpdate: (id: string, data: UserData) => void;
}

// ❌ Avoid: Generic types
props: {
  status: string;
  count: any;
  onUpdate: Function;
}

State Structure:

// ✅ Good: Hierarchical, typed structure
{
  ui: {
    theme: 'light' | 'dark',
    modal: { open: boolean, content: string | null }
  },
  data: {
    users: User[],
    loading: boolean,
    error: string | null
  }
}

// ❌ Avoid: Flat, untyped structure
{
  theme: any,
  modalOpen: any,
  modalContent: any,
  users: any,
  loading: any
}

3. Error Handling

Graceful Degradation:

export const SafeComponent = (props, context) => {
    const { data, fallback } = props;
    
    // Handle missing data
    if (!data || data.length === 0) {
        return fallback || { div: { text: 'No data available' } };
    }
    
    // Handle errors in rendering
    try {
        return {
            div: {
                children: data.map(item => ({
                    div: { text: item.name || 'Unknown' }
                }))
            }
        };
    } catch (error) {
        console.error('Rendering error:', error);
        return { div: { text: 'Error rendering component' } };
    }
};

Type Guards:

/**
 * @param {any} value
 * @returns {value is User}
 */
function isUser(value) {
    return value && 
           typeof value.id === 'number' &&
           typeof value.name === 'string' &&
           typeof value.email === 'string';
}

export const UserComponent = (props, context) => {
    const { user } = props;
    
    if (!isUser(user)) {
        return { div: { text: 'Invalid user data' } };
    }
    
    // Now TypeScript knows user is a valid User
    return {
        div: {
            text: `${user.name} (${user.email})`
        }
    };
};

4. Performance

Memoization:

export const ExpensiveComponent = (props, context) => {
    const { data } = props;
    const { getState } = context;
    
    // Cache expensive computations
    const processedData = useMemo(() => {
        return data.map(item => ({
            ...item,
            processed: expensiveFunction(item)
        }));
    }, [data]);
    
    return {
        div: {
            children: processedData.map(item => ({
                div: { text: item.processed }
            }))
        }
    };
};

Lazy Loading:

export const LazyComponent = (props, context) => {
    const { shouldLoad } = props;
    
    if (!shouldLoad) {
        return { div: { text: 'Click to load content' } };
    }
    
    return {
        div: {
            children: async () => {
                const data = await loadExpensiveData();
                return data.map(item => ({
                    div: { text: item.title }
                }));
            }
        }
    };
};

5. Testing

Component Testing:

// test/components/UserCard.test.js
import { UserCard } from '../components/UserCard.js';

/**
 * @param {import('@types').JurisVDOMElement} element
 */
function renderToString(element) {
    // Convert VDOM to string for testing
    const tagName = Object.keys(element)[0];
    const props = element[tagName];
    return `<${tagName}>${props.text || ''}</${tagName}>`;
}

describe('UserCard', () => {
    test('renders user name and email', () => {
        const mockContext = {
            getState: () => null,
            setState: () => {},
            services: {}
        };
        
        const props = {
            user: { id: 1, name: 'John', email: '[email protected]' },
            theme: 'light'
        };
        
        const element = UserCard(props, mockContext);
        const html = renderToString(element);
        
        expect(html).toContain('John');
        expect(html).toContain('[email protected]');
    });
});

6. Documentation

Component Documentation:

/**
 * UserCard - Displays user information in a card format
 * 
 * @example
 * ```javascript
 * {
 *   UserCard: {
 *     props: {
 *       user: { id: 1, name: 'John', email: 'john@test.com' },
 *       theme: 'dark',
 *       onEdit: (user) => console.log('Edit:', user)
 *     }
 *   }
 * }
 * ```
 * 
 * @param {{
 *   user: {id: number, name: string, email: string, avatar?: string},
 *   theme?: 'light' | 'dark',
 *   onEdit?: (user: User) => void,
 *   onDelete?: (userId: number) => void
 * }} props
 * @param {import('@types').JurisContext} context
 * @returns {import('@types').JurisVDOMElement}
 */
export const UserCard = (props, context) => {
    // Implementation...
};

🎉 Conclusion

The Juris Types system provides enterprise-grade type safety for modern web applications. By combining TypeScript's static analysis with Juris's reactive patterns, you get:

  • Immediate error detection during development
  • Framework-aware validation that understands VDOM and components
  • Excellent developer experience with full IntelliSense support
  • Scalable architecture for teams and large applications

Start with basic component typing and gradually add more sophisticated patterns as your application grows. The type system will guide you toward better code organization and help prevent runtime errors.

Happy coding with Juris Types! 🚀


📖 Additional Resources

🤝 Contributing

Found an issue or want to improve the types? Contributions are welcome!

  1. Fork the repository
  2. Create a feature branch
  3. Add your improvements
  4. Submit a pull request

For type-related contributions, please include:

  • Updated type definitions
  • Usage examples
  • Documentation updates
  • Test cases (if applicable)
⚠️ **GitHub.com Fallback** ⚠️