core icon indicating copy to clipboard operation
core copied to clipboard

TypeScript Migration Development

Open deeptanildebroy opened this issue 10 months ago • 0 comments

Proof of Concept (PoC): Encapsulation of Prop Metadata for CoreDivider Component

1. Introduction

This document provides a Proof of Concept (PoC) for encapsulating prop metadata in the CoreDivider component using CorePropDefinition and CorePropTypeDefinition. The approach enhances type safety, validation, and maintainability while ensuring a scalable architecture for managing component props.

2. Motivation

2.1 Problems with Traditional Prop Handling

  • Prop validation is often handled inline within components, leading to duplication.
  • Lack of strong typing can result in runtime errors and inconsistencies.
  • Maintaining large-scale components with many props becomes difficult.

2.2 Advantages of the Proposed Approach

  • Encapsulation of Prop Metadata: Using CorePropDefinition and CorePropTypeDefinition centralizes prop configurations, making the system reusable and maintainable.
  • Type Safety with TypeScript: Strongly typed definitions reduce errors and improve maintainability.
  • Enhanced Validation Support: Built-in support for constraints like validValues, default, constraints, and required.
  • Centralized Prop Configuration: Defining valid and invalid props separately improves modularity and avoids duplication.

3. Implementation

3.1 Core Divider Component (CoreDivider.tsx)

import React from "react";
import { NativeDivider } from "@wrappid/native";
import { sanitizeComponentProps } from "../../../utils/componentUtil";
import { validProps, invalidProps } from "./CoreDividerProps";

export interface CoreDividerProps {
  absolute?: boolean;
  component?: React.ElementType;
  flexItem?: boolean;
  light?: boolean;
  orientation?: "horizontal" | "vertical";
  textAlign?: "center" | "left" | "right";
  variant?: "fullWidth" | "inset" | "middle";
  leftInset?: boolean;
  horizontalInset?: boolean;
  bold?: boolean;
  children?: React.ReactNode;
}

interface CoreDividerComponent extends React.FC<CoreDividerProps> {
  validProps: typeof validProps;
  invalidProps: typeof invalidProps;
}

const CoreDivider: CoreDividerComponent = (props) => {
  const sanitizedProps = sanitizeComponentProps(CoreDivider, props) as CoreDividerProps;
  const { children, ...restProps } = sanitizedProps;
  return <NativeDivider {...restProps}>{children}</NativeDivider>;
};

CoreDivider.validProps = validProps;
CoreDivider.invalidProps = invalidProps;

export default CoreDivider;

3.2 Core Prop Definitions (CorePropDefinition.ts)

export class CorePropTypeDefinition {
  default?: any;
  type: string;
  validValues?: any[];
  
  constructor(type: string, defaultValue?: any, validValues?: any[]) {
    this.type = type;
    this.default = defaultValue;
    this.validValues = validValues;
  }
}

export class CorePropDefinition {
  description?: string;
  name: string;
  types: CorePropTypeDefinition[];
  
  constructor(name: string, types: CorePropTypeDefinition[], description?: string) {
    this.name = name;
    this.types = types;
    this.description = description;
  }
}

3.3 Centralized Prop Metadata (CoreDividerProps.ts)

import { CorePropDefinition, CorePropTypeDefinition } from "./CorePropDefinition";

export const validProps: CorePropDefinition[] = [
  new CorePropDefinition("absolute", [new CorePropTypeDefinition("boolean", false, [true, false])], "Absolutely position the element."),
  new CorePropDefinition("component", [new CorePropTypeDefinition("elementType")], "The component used for the root node."),
  new CorePropDefinition("flexItem", [new CorePropTypeDefinition("boolean", false, [true, false])], "Ensures correct height in flex containers."),
  new CorePropDefinition("light", [new CorePropTypeDefinition("boolean", false, [true, false])], "If true, applies a lighter color."),
  new CorePropDefinition("orientation", [new CorePropTypeDefinition("string", "horizontal", ["horizontal", "vertical"])], "Determines component orientation."),
  new CorePropDefinition("textAlign", [new CorePropTypeDefinition("string", "center", ["center", "left", "right"])], "Determines text alignment."),
  new CorePropDefinition("variant", [new CorePropTypeDefinition("string", "fullWidth", ["fullWidth", "inset", "middle"])], "Defines the divider variant."),
  new CorePropDefinition("leftInset", [new CorePropTypeDefinition("boolean", undefined, [true, false])]),
  new CorePropDefinition("horizontalInset", [new CorePropTypeDefinition("boolean", undefined, [true, false])]),
  new CorePropDefinition("bold", [new CorePropTypeDefinition("boolean", undefined, [true, false])]),
];

export const invalidProps: string[] = ["style", "theme"];

4. Key Benefits of This Approach

4.1 Encapsulation of Prop Metadata

  • The CorePropDefinition and CorePropTypeDefinition classes provide a structured way to define and manage prop metadata.
  • Helps in reducing redundant prop definitions across different components.

4.2 Type Safety with TypeScript

  • Strongly typed definitions ensure better tooling support and reduce runtime errors.
  • The React.ElementType type for the component prop allows proper validation for custom component overrides.

4.3 Enhanced Validation Support

  • Built-in support for validValues, default, constraints, and required improves type checking.
  • The deprecated and replacement fields allow future-proofing and better API evolution.

4.4 Centralized Prop Configuration

  • Having a single CoreDividerProps.ts file for valid and invalid props enhances maintainability.
  • Helps in ensuring consistency across components while allowing easy modifications.

5. Conclusion

This PoC demonstrates how encapsulating prop metadata using TypeScript and object-oriented principles significantly improves maintainability, scalability, and type safety. The approach ensures that prop definitions are centralized, reusable, and easier to validate. This method provides a structured, future-proof way to manage props, making it ideal for large-scale component-driven applications.

deeptanildebroy avatar Feb 22 '25 18:02 deeptanildebroy