Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 41 additions & 17 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,33 +166,57 @@ const result = await generateCode({
- <mcfile name="typebox-call.ts" path="src/utils/typebox-call.ts"></mcfile>: Contains the core logic for converting TypeScript type nodes into TypeBox `Type` expressions. `getTypeBoxType` takes a `TypeNode` as input and returns a `ts.Node` representing the equivalent TypeBox schema.
- <mcfile name="add-static-type-alias.ts" path="src/utils/add-static-type-alias.ts"></mcfile>: Generates and adds the `export type [TypeName] = Static<typeof [TypeName]>` declaration to the output source file. This declaration is essential for enabling TypeScript's static type inference from the dynamically generated TypeBox schemas, ensuring type safety at compile time.
- <mcfile name="typebox-codegen-utils.ts" path="src/utils/typebox-codegen-utils.ts"></mcfile>: Contains general utility functions that support the TypeBox code generation process, such as helper functions for string manipulation or AST node creation.
- <mcfile name="typescript-ast-parser.ts" path="src/utils/typescript-ast-parser.ts"></mcfile>: Responsible for parsing TypeScript source code and extracting relevant Abstract Syntax Tree (AST) information. It provides functions to navigate the AST and identify specific nodes like type aliases, interfaces, or enums.
- <mcfile name="typescript-ast-types.ts" path="src/utils/typescript-ast-types.ts"></mcfile>: Defines custom types and interfaces that represent the structured AST information extracted by `typescript-ast-parser.ts`, providing a consistent data model for further processing.

### Handlers Directory

This directory contains a collection of specialized handler modules, each responsible for converting a specific type of TypeScript AST node into its corresponding TypeBox schema. This modular approach allows for easy extension and maintenance of the type mapping logic.
This directory contains a collection of specialized handler modules, each responsible for converting a specific type of TypeScript AST node into its corresponding TypeBox schema. The handlers follow a hierarchical architecture with specialized base classes to reduce code duplication and ensure consistent behavior.

#### Base Handler Classes

- <mcfile name="base-type-handler.ts" path="src/handlers/typebox/base-type-handler.ts"></mcfile>: The root abstract base class that defines the common interface for all type handlers. Provides the `canHandle` and `handle` methods, along with utility functions like `makeTypeCall` for creating TypeBox expressions.
- <mcfile name="type-reference-base-handler.ts" path="src/handlers/typebox/reference/type-reference-base-handler.ts"></mcfile>: Specialized base class for utility type handlers that work with TypeScript type references. Provides `validateTypeReference` and `extractTypeArguments` methods for consistent handling of generic utility types like `Partial<T>`, `Pick<T, K>`, etc.
- <mcfile name="object-like-base-handler.ts" path="src/handlers/typebox/object/object-like-base-handler.ts"></mcfile>: Base class for handlers that process object-like structures (objects and interfaces). Provides `processProperties`, `extractProperties`, and `createObjectType` methods for consistent property handling and TypeBox object creation.
- <mcfile name="collection-base-handler.ts" path="src/handlers/typebox/collection/collection-base-handler.ts"></mcfile>: Base class for handlers that work with collections of types (arrays, tuples, unions, intersections). Provides `processTypeCollection`, `processSingleType`, and `validateNonEmptyCollection` methods for consistent type collection processing.

Comment on lines +172 to +180
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Clarify BaseTypeHandler description and reference to makeTypeCall.

makeTypeCall lives in src/utils/typebox-codegen-utils.ts, not in the base handler. Reword to avoid implying it’s provided by the base class. Also consider listing the new processor you added in this PR so readers can find it.

- - <mcfile name="base-type-handler.ts" path="src/handlers/typebox/base-type-handler.ts"></mcfile>: The root abstract base class that defines the common interface for all type handlers. Provides the `canHandle` and `handle` methods, along with utility functions like `makeTypeCall` for creating TypeBox expressions.
+ - <mcfile name="base-type-handler.ts" path="src/handlers/typebox/base-type-handler.ts"></mcfile>: The root abstract base class that defines the common interface for all type handlers. It provides the `canHandle` and `handle` methods. Implementations use helpers such as `makeTypeCall` (see <mcfile name="typebox-codegen-utils.ts" path="src/utils/typebox-codegen-utils.ts"></mcfile>) to create TypeBox expressions.

And add the missing processor reference:

- - <mcfile name="template-literal-type-handler.ts" path="src/handlers/typebox/template-literal-type-handler.ts"></mcfile>: Handles TypeScript template literal types (e.g., `` `hello-${string}` ``). Parses template literals into components, handling literal text, embedded types (string, number, unions), and string/numeric literals.
+ - <mcfile name="template-literal-type-handler.ts" path="src/handlers/typebox/template-literal-type-handler.ts"></mcfile>: Handles TypeScript template literal types (e.g., `` `hello-${string}` ``). Parses template literals into components, handling literal text and embedded types (string/number/boolean, unions).
+ - <mcfile name="template-literal-type-processor.ts" path="src/handlers/typebox/template-literal-type-processor.ts"></mcfile>: Utility used by the TemplateLiteralTypeHandler to translate substitution nodes into precise TypeBox expressions (literals, unions, or fallbacks).

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In ARCHITECTURE.md around lines 172 to 180, the Base Handler Classes section
incorrectly implies makeTypeCall is provided by the base handler and omits the
new processor added in this PR; update the text to state that makeTypeCall is
located in src/utils/typebox-codegen-utils.ts (not in base-type-handler.ts),
reword the base-type-handler description to only list methods it actually
provides (canHandle, handle, etc.), and add a short entry naming and linking the
new processor file you introduced so readers can find it.

#### Type Handler Implementations

**Utility Type Handlers** (extend `TypeReferenceBaseHandler`):

- <mcfile name="partial-type-handler.ts" path="src/handlers/typebox/reference/partial-type-handler.ts"></mcfile>: Handles TypeScript `Partial` utility types.
- <mcfile name="pick-type-handler.ts" path="src/handlers/typebox/reference/pick-type-handler.ts"></mcfile>: Handles TypeScript `Pick` utility types.
- <mcfile name="omit-type-handler.ts" path="src/handlers/typebox/reference/omit-type-handler.ts"></mcfile>: Handles TypeScript `Omit` utility types.
- <mcfile name="required-type-handler.ts" path="src/handlers/typebox/reference/required-type-handler.ts"></mcfile>: Handles TypeScript `Required` utility types.
- <mcfile name="record-type-handler.ts" path="src/handlers/typebox/reference/record-type-handler.ts"></mcfile>: Handles TypeScript `Record` utility types.

**Object-Like Type Handlers** (extend `ObjectLikeBaseHandler`):

- <mcfile name="object-type-handler.ts" path="src/handlers/typebox/object/object-type-handler.ts"></mcfile>: Handles TypeScript object types and type literals.
- <mcfile name="interface-type-handler.ts" path="src/handlers/typebox/object/interface-type-handler.ts"></mcfile>: Handles TypeScript interface declarations.

**Collection Type Handlers** (extend `CollectionBaseHandler`):

- <mcfile name="array-type-handler.ts" path="src/handlers/typebox/collection/array-type-handler.ts"></mcfile>: Handles TypeScript array types (e.g., `string[]`, `Array<number>`).
- <mcfile name="tuple-type-handler.ts" path="src/handlers/typebox/collection/tuple-type-handler.ts"></mcfile>: Handles TypeScript tuple types.
- <mcfile name="union-type-handler.ts" path="src/handlers/typebox/collection/union-type-handler.ts"></mcfile>: Handles TypeScript union types (e.g., `string | number`).
- <mcfile name="intersection-type-handler.ts" path="src/handlers/typebox/collection/intersection-type-handler.ts"></mcfile>: Handles TypeScript intersection types (e.g., `TypeA & TypeB`).

**Standalone Type Handlers** (extend `BaseTypeHandler`):

- <mcfile name="array-type-handler.ts" path="src/handlers/typebox/array-type-handler.ts"></mcfile>: Handles TypeScript array types (e.g., `string[]`, `Array<number>`).
- <mcfile name="indexed-access-type-handler.ts" path="src/handlers/typebox/indexed-access-type-handler.ts"></mcfile>: Handles TypeScript indexed access types (e.g., `Type[Key]`).
- <mcfile name="intersection-type-handler.ts" path="src/handlers/typebox/intersection-type-handler.ts"></mcfile>: Handles TypeScript intersection types (e.g., `TypeA & TypeB`).
- <mcfile name="literal-type-handler.ts" path="src/handlers/typebox/literal-type-handler.ts"></mcfile>: Handles TypeScript literal types (e.g., `'hello'`, `123`, `true`).
- <mcfile name="object-type-handler.ts" path="src/handlers/typebox/object-type-handler.ts"></mcfile>: Handles TypeScript object types and interfaces.
- <mcfile name="omit-type-handler.ts" path="src/handlers/typebox/omit-type-handler.ts"></mcfile>: Handles TypeScript `Omit` utility types.
- <mcfile name="partial-type-handler.ts" path="src/handlers/typebox/partial-type-handler.ts"></mcfile>: Handles TypeScript `Partial` utility types.
- <mcfile name="pick-type-handler.ts" path="src/handlers/typebox/pick-type-handler.ts"></mcfile>: Handles TypeScript `Pick` utility types.
- <mcfile name="required-type-handler.ts" path="src/handlers/typebox/required-type-handler.ts"></mcfile>: Handles TypeScript `Required` utility types.
- <mcfile name="record-type-handler.ts" path="src/handlers/typebox/record-type-handler.ts"></mcfile>: Handles TypeScript `Record` utility types.
- <mcfile name="simple-type-handler.ts" path="src/handlers/typebox/simple-type-handler.ts"></mcfile>: Handles basic TypeScript types like `string`, `number`, `boolean`, `null`, `undefined`, `any`, `unknown`, `void`.
- <mcfile name="literal-type-handler.ts" path="src/handlers/typebox/literal-type-handler.ts"></mcfile>: Handles TypeScript literal types (e.g., `'hello'`, `123`, `true`).
- <mcfile name="function-type-handler.ts" path="src/handlers/typebox/function-type-handler.ts"></mcfile>: Handles TypeScript function types and function declarations, including parameter types, optional parameters, and return types.
Comment on lines 205 to 207
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Minor grammar/style polish in handler list.

Tighten wording and ensure consistency in the list entries (LanguageTool flagged this area).

- - <mcfile name="literal-type-handler.ts" path="src/handlers/typebox/literal-type-handler.ts"></mcfile>: Handles TypeScript literal types (e.g., `'hello'`, `123`, `true`).
+ - <mcfile name="literal-type-handler.ts" path="src/handlers/typebox/literal-type-handler.ts"></mcfile>: Handles TypeScript literal types (for example, `'hello'`, `123`, `true`).
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- <mcfile name="simple-type-handler.ts" path="src/handlers/typebox/simple-type-handler.ts"></mcfile>: Handles basic TypeScript types like `string`, `number`, `boolean`, `null`, `undefined`, `any`, `unknown`, `void`.
- <mcfile name="literal-type-handler.ts" path="src/handlers/typebox/literal-type-handler.ts"></mcfile>: Handles TypeScript literal types (e.g., `'hello'`, `123`, `true`).
- <mcfile name="function-type-handler.ts" path="src/handlers/typebox/function-type-handler.ts"></mcfile>: Handles TypeScript function types and function declarations, including parameter types, optional parameters, and return types.
- <mcfile name="simple-type-handler.ts" path="src/handlers/typebox/simple-type-handler.ts"></mcfile>: Handles basic TypeScript types like `string`, `number`, `boolean`, `null`, `undefined`, `any`, `unknown`, `void`.
- <mcfile name="literal-type-handler.ts" path="src/handlers/typebox/literal-type-handler.ts"></mcfile>: Handles TypeScript literal types (for example, `'hello'`, `123`, `true`).
- <mcfile name="function-type-handler.ts" path="src/handlers/typebox/function-type-handler.ts"></mcfile>: Handles TypeScript function types and function declarations, including parameter types, optional parameters, and return types.
🧰 Tools
🪛 LanguageTool

[grammar] ~205-~205: There might be a mistake here.
Context: ..., undefined, any, unknown, void. - : Handles TypeScript literal types (e.g....

(QB_NEW_EN)


[grammar] ~207-~207: There might be a mistake here.
Context: ..., optional parameters, and return types. - : Handles TypeScript template literal ty...

(QB_NEW_EN)

🤖 Prompt for AI Agents
In ARCHITECTURE.md around lines 205 to 207, the three handler list entries need
parallel, tightened wording and consistent punctuation; revise each bullet to
start with the same verb ("Handles"), remove redundant phrasing (avoid repeating
"TypeScript" where unnecessary), make examples parenthetical and parallel (e.g.,
"(e.g., 'hello', 123, true)"), and ensure consistent punctuation style across
all items (same sentence fragment style and use of periods or no periods).

- <mcfile name="template-literal-type-handler.ts" path="src/handlers/typebox/template-literal-type-handler.ts"></mcfile>: Handles TypeScript template literal types (e.g., `` `hello-${string}` ``). Parses template literals into components, handling literal text, embedded types (string, number, unions), and string/numeric literals.
- <mcfile name="typeof-type-handler.ts" path="src/handlers/typebox/typeof-type-handler.ts"></mcfile>: Handles TypeScript `typeof` expressions for extracting types from values.
- <mcfile name="tuple-type-handler.ts" path="src/handlers/typebox/tuple-type-handler.ts"></mcfile>: Handles TypeScript tuple types.
- <mcfile name="type-operator-handler.ts" path="src/handlers/typebox/type-operator-handler.ts"></mcfile>: Handles TypeScript type operators like `keyof`, `typeof`.
- <mcfile name="keyof-type-handler.ts" path="src/handlers/typebox/keyof-type-handler.ts"></mcfile>: Handles TypeScript `keyof` type operator for extracting object keys.
- <mcfile name="readonly-type-handler.ts" path="src/handlers/typebox/readonly-type-handler.ts"></mcfile>: Handles TypeScript `readonly` type modifier for creating immutable types.
- <mcfile name="type-operator-handler.ts" path="src/handlers/typebox/type-operator-handler.ts"></mcfile>: Fallback handler for other TypeScript type operators not covered by specific handlers.
- <mcfile name="type-reference-handler.ts" path="src/handlers/typebox/type-reference-handler.ts"></mcfile>: Handles references to other types (e.g., `MyType`).
- <mcfile name="indexed-access-type-handler.ts" path="src/handlers/typebox/indexed-access-type-handler.ts"></mcfile>: Handles TypeScript indexed access types (e.g., `Type[Key]`).
- <mcfile name="typebox-type-handler.ts" path="src/handlers/typebox/typebox-type-handler.ts"></mcfile>: A generic handler for TypeBox types.
- <mcfile name="typebox-type-handlers.ts" path="src/handlers/typebox/typebox-type-handlers.ts"></mcfile>: Orchestrates the use of the individual type handlers, acting as a dispatcher based on the type of AST node encountered.
- <mcfile name="union-type-handler.ts" path="src/handlers/typebox/union-type-handler.ts"></mcfile>: Handles TypeScript union types (e.g., `string | number`).

**Handler Orchestration**:

- <mcfile name="typebox-type-handlers.ts" path="src/handlers/typebox/typebox-type-handlers.ts"></mcfile>: Orchestrates the use of the individual type handlers, acting as a dispatcher based on the type of AST node encountered. Uses optimized lookup mechanisms for performance with O(1) syntax kind-based lookups and type reference name mappings. Includes specialized handlers for type operators (KeyOfTypeHandler, TypeofTypeHandler, ReadonlyTypeHandler) and maintains fallback handlers for edge cases requiring custom logic.

### Parsers Directory

Expand Down
22 changes: 0 additions & 22 deletions src/handlers/typebox/array-type-handler.ts

This file was deleted.

10 changes: 2 additions & 8 deletions src/handlers/typebox/base-type-handler.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
import { Node, ts } from 'ts-morph'

export abstract class BaseTypeHandler {
protected getTypeBoxType: (typeNode?: Node) => ts.Expression

constructor(getTypeBoxType: (typeNode?: Node) => ts.Expression) {
this.getTypeBoxType = getTypeBoxType
}

abstract canHandle(typeNode: Node | undefined): boolean
abstract handle(typeNode: Node | undefined): ts.Expression
abstract canHandle(node: Node): boolean
abstract handle(node: Node): ts.Expression
}
12 changes: 12 additions & 0 deletions src/handlers/typebox/collection/array-type-handler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { CollectionBaseHandler } from '@daxserver/validation-schema-codegen/handlers/typebox/collection/collection-base-handler'
import { ArrayTypeNode, Node, ts } from 'ts-morph'

export class ArrayTypeHandler extends CollectionBaseHandler {
canHandle(node: Node): boolean {
return Node.isArrayTypeNode(node)
}

handle(node: ArrayTypeNode): ts.Expression {
return this.processSingleType(node.getElementTypeNode(), 'Array')
}
}
23 changes: 23 additions & 0 deletions src/handlers/typebox/collection/collection-base-handler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { BaseTypeHandler } from '@daxserver/validation-schema-codegen/handlers/typebox/base-type-handler'
import { getTypeBoxType } from '@daxserver/validation-schema-codegen/utils/typebox-call'
import { makeTypeCall } from '@daxserver/validation-schema-codegen/utils/typebox-codegen-utils'
import { Node, ts } from 'ts-morph'

export abstract class CollectionBaseHandler extends BaseTypeHandler {
protected processTypeCollection(nodes: Node[], typeBoxFunction: string): ts.Expression {
const typeBoxTypes = nodes.map((node) => getTypeBoxType(node))
const arrayLiteral = ts.factory.createArrayLiteralExpression(typeBoxTypes)

return makeTypeCall(typeBoxFunction, [arrayLiteral])
}

protected processSingleType(node: Node, typeBoxFunction: string): ts.Expression {
return makeTypeCall(typeBoxFunction, [getTypeBoxType(node)])
}

protected validateNonEmptyCollection(nodes: Node[], typeName: string): void {
if (nodes.length === 0) {
throw new Error(`${typeName} must have at least one type`)
}
}
}
12 changes: 12 additions & 0 deletions src/handlers/typebox/collection/intersection-type-handler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { CollectionBaseHandler } from '@daxserver/validation-schema-codegen/handlers/typebox/collection/collection-base-handler'
import { IntersectionTypeNode, Node, ts } from 'ts-morph'

export class IntersectionTypeHandler extends CollectionBaseHandler {
canHandle(node: Node): boolean {
return Node.isIntersectionTypeNode(node)
}

handle(node: IntersectionTypeNode): ts.Expression {
return this.processTypeCollection(node.getTypeNodes(), 'Intersect')
}
}
12 changes: 12 additions & 0 deletions src/handlers/typebox/collection/tuple-type-handler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { CollectionBaseHandler } from '@daxserver/validation-schema-codegen/handlers/typebox/collection/collection-base-handler'
import { Node, ts, TupleTypeNode } from 'ts-morph'

export class TupleTypeHandler extends CollectionBaseHandler {
canHandle(node: Node): boolean {
return Node.isTupleTypeNode(node)
}

handle(node: TupleTypeNode): ts.Expression {
return this.processTypeCollection(node.getElements(), 'Tuple')
}
Comment on lines +9 to +11
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Bug: tuple elements may be NamedTupleMember/RestTypeNode — pass their inner TypeNodes to avoid generating Any

node.getElements() returns element nodes (e.g., NamedTupleMember, RestTypeNode), not always TypeNodes. Forwarding them directly to a generic collection processor risks falling back to Any. Extract the element type nodes first.

Apply this diff:

-  handle(node: TupleTypeNode): ts.Expression {
-    return this.processTypeCollection(node.getElements(), 'Tuple')
-  }
+  handle(node: TupleTypeNode): ts.Expression {
+    const elementTypeNodes = node.getElements().map((el) => {
+      if (Node.isNamedTupleMember(el) || Node.isRestTypeNode(el)) {
+        return el.getTypeNode()
+      }
+      // Fallback: if it's already a TypeNode, keep as is.
+      return Node.isTypeNode(el) ? el : undefined
+    }).filter((n): n is Node => !!n)
+
+    return this.processTypeCollection(elementTypeNodes, 'Tuple')
+  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
handle(node: TupleTypeNode): ts.Expression {
return this.processTypeCollection(node.getElements(), 'Tuple')
}
handle(node: TupleTypeNode): ts.Expression {
const elementTypeNodes = node
.getElements()
.map((el) => {
if (Node.isNamedTupleMember(el) || Node.isRestTypeNode(el)) {
return el.getTypeNode()
}
// Fallback: if it's already a TypeNode, keep as is.
return Node.isTypeNode(el) ? el : undefined
})
.filter((n): n is Node => !!n)
return this.processTypeCollection(elementTypeNodes, 'Tuple')
}
🤖 Prompt for AI Agents
In src/handlers/typebox/collection/tuple-type-handler.ts around lines 9 to 11,
the handler forwards node.getElements() directly but those elements can be
NamedTupleMember or RestTypeNode (not raw TypeNodes), causing the processor to
fall back to Any; update the method to map node.getElements() to an array of
inner TypeNodes by extracting .type from NamedTupleMember and .type from
RestTypeNode (or using the element itself if it's already a TypeNode), then pass
that array of TypeNodes to this.processTypeCollection('Tuple') so the correct
inner types are processed.

}
12 changes: 12 additions & 0 deletions src/handlers/typebox/collection/union-type-handler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { CollectionBaseHandler } from '@daxserver/validation-schema-codegen/handlers/typebox/collection/collection-base-handler'
import { Node, ts, UnionTypeNode } from 'ts-morph'

export class UnionTypeHandler extends CollectionBaseHandler {
canHandle(node: Node): boolean {
return Node.isUnionTypeNode(node)
}

handle(node: UnionTypeNode): ts.Expression {
return this.processTypeCollection(node.getTypeNodes(), 'Union')
}
}
25 changes: 9 additions & 16 deletions src/handlers/typebox/function-type-handler.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,21 @@
import { BaseTypeHandler } from '@daxserver/validation-schema-codegen/handlers/typebox/base-type-handler'
import { getTypeBoxType } from '@daxserver/validation-schema-codegen/utils/typebox-call'
import { makeTypeCall } from '@daxserver/validation-schema-codegen/utils/typebox-codegen-utils'
import { Node, ts } from 'ts-morph'
import { FunctionTypeNode, Node, ts } from 'ts-morph'

export class FunctionTypeHandler extends BaseTypeHandler {
constructor(getTypeBoxType: (typeNode?: Node) => ts.Expression) {
super(getTypeBoxType)
canHandle(node: Node): boolean {
return Node.isFunctionTypeNode(node)
}

canHandle(typeNode?: Node): boolean {
return Node.isFunctionTypeNode(typeNode)
}

handle(typeNode: Node): ts.Expression {
if (!Node.isFunctionTypeNode(typeNode)) {
return makeTypeCall('Any')
}

const parameters = typeNode.getParameters()
const returnType = typeNode.getReturnTypeNode()
handle(node: FunctionTypeNode): ts.Expression {
const parameters = node.getParameters()
const returnType = node.getReturnTypeNode()

// Convert parameters to TypeBox types
const parameterTypes = parameters.map((param) => {
const paramTypeNode = param.getTypeNode()
const paramType = this.getTypeBoxType(paramTypeNode)
const paramType = getTypeBoxType(paramTypeNode)

// Check if parameter is optional
if (param.hasQuestionToken()) {
Expand All @@ -33,7 +26,7 @@ export class FunctionTypeHandler extends BaseTypeHandler {
})

// Convert return type to TypeBox type
const returnTypeBox = this.getTypeBoxType(returnType)
const returnTypeBox = getTypeBoxType(returnType)

// Create TypeBox Function call with parameters array and return type
return makeTypeCall('Function', [
Expand Down
22 changes: 11 additions & 11 deletions src/handlers/typebox/indexed-access-type-handler.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
import { BaseTypeHandler } from '@daxserver/validation-schema-codegen/handlers/typebox/base-type-handler'
import { getTypeBoxType } from '@daxserver/validation-schema-codegen/utils/typebox-call'
import { makeTypeCall } from '@daxserver/validation-schema-codegen/utils/typebox-codegen-utils'
import { IndexedAccessTypeNode, Node, ts } from 'ts-morph'

export class IndexedAccessTypeHandler extends BaseTypeHandler {
canHandle(node: Node | undefined): boolean {
return node !== undefined && node.isKind(ts.SyntaxKind.IndexedAccessType)
canHandle(node: Node): boolean {
return node.isKind(ts.SyntaxKind.IndexedAccessType)
}

handle(node: Node): ts.Expression {
const typeNode = node as IndexedAccessTypeNode
const objectType = typeNode.getObjectTypeNode()
const indexType = typeNode.getIndexTypeNode()
handle(node: IndexedAccessTypeNode): ts.Expression {
const objectType = node.getObjectTypeNode()
const indexType = node.getIndexTypeNode()

// Handle special case: typeof A[number] where A is a readonly tuple
if (
objectType?.isKind(ts.SyntaxKind.TypeQuery) &&
indexType?.isKind(ts.SyntaxKind.NumberKeyword)
) {
return this.handleTypeofArrayAccess(objectType, typeNode)
return this.handleTypeofArrayAccess(objectType, node)
}

const typeboxObjectType = this.getTypeBoxType(objectType)
const typeboxIndexType = this.getTypeBoxType(indexType)
const typeboxObjectType = getTypeBoxType(objectType)
const typeboxIndexType = getTypeBoxType(indexType)

return makeTypeCall('Index', [typeboxObjectType, typeboxIndexType])
}
Expand Down Expand Up @@ -58,8 +58,8 @@ export class IndexedAccessTypeHandler extends BaseTypeHandler {
}

// Fallback to default Index behavior
const typeboxObjectType = this.getTypeBoxType(typeQuery)
const typeboxIndexType = this.getTypeBoxType(indexedAccessType.getIndexTypeNode())
const typeboxObjectType = getTypeBoxType(typeQuery)
const typeboxIndexType = getTypeBoxType(indexedAccessType.getIndexTypeNode())
return makeTypeCall('Index', [typeboxObjectType, typeboxIndexType])
}

Expand Down
Loading