Skip to content

Commit

Permalink
chore: improve ternary types
Browse files Browse the repository at this point in the history
chore: wip

chore: wip

chore: wip
  • Loading branch information
chrisbbreuer committed Nov 25, 2024
1 parent e475fe6 commit e23f56b
Show file tree
Hide file tree
Showing 5 changed files with 116 additions and 37 deletions.
16 changes: 16 additions & 0 deletions fixtures/input/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,19 @@ export type DynamicRecord<K extends PropertyKey> = {
? Record<string, unknown>
: never
}

export type RecordMerge<T, U> = IsEmptyType<U> extends true
? T
: [T, U] extends [any[], any[]]
? U
: [T, U] extends [object, object]
? {
[K in keyof T | keyof U]: K extends keyof T
? K extends keyof U
? RecordMerge<T[K], U[K]>
: T[K]
: K extends keyof U
? U[K]
: never
}
: U
2 changes: 1 addition & 1 deletion fixtures/output/0003.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ declare interface AutoImportsPlugin {
export declare function autoImports(options: Partial<UnimportOptions & { dts: string }>): AutoImportsPlugin;
export declare type AutoImportsOptions = UnimportOptions

export default autoImports;
export default autoImports
27 changes: 18 additions & 9 deletions fixtures/output/0004.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ export declare interface DtsGenerationConfig {
verbose: boolean
}
export declare type DtsGenerationOption = Partial<DtsGenerationConfig>
export declare type DtsGenerationOptions = DtsGenerationOption | DtsGenerationOption[]
export declare interface RegexPatterns {

export type DtsGenerationOptions = DtsGenerationOption | DtsGenerationOption[]

export interface RegexPatterns {
readonly typeImport: RegExp
readonly regularImport: RegExp
readonly bracketOpen: RegExp
Expand All @@ -37,7 +39,8 @@ export declare interface RegexPatterns {
readonly moduleDeclaration: RegExp
readonly moduleAugmentation: RegExp
}
export declare interface ImportTrackingState {

export interface ImportTrackingState {
typeImports: Map<string, Set<string>>
valueImports: Map<string, Set<string>>
usedTypes: Set<string>
Expand All @@ -49,7 +52,8 @@ export declare interface ImportTrackingState {
typeExportSources: Map<string, string>
defaultExportValue?: string
}
export declare interface ProcessingState {

export interface ProcessingState {
dtsLines: string[]
imports: string[]
usedTypes: Set<string>
Expand All @@ -74,33 +78,38 @@ export declare interface ProcessingState {
defaultExports: Set<string>
currentScope: 'top' | 'function'
}
export declare interface MethodSignature {

export interface MethodSignature {
name: string
async: boolean
generics: string
params: string
returnType: string
}
export declare interface PropertyInfo {

export interface PropertyInfo {
key: string
value: string
type: string
nested?: PropertyInfo[]
method?: MethodSignature
}
export declare interface ImportInfo {

export interface ImportInfo {
kind: 'type' | 'value' | 'mixed'
usedTypes: Set<string>
usedValues: Set<string>
source: string
}
export declare interface FunctionSignature {

export interface FunctionSignature {
name: string
params: string
returnType: string
generics: string
}
export declare interface ProcessedMethod {

export interface ProcessedMethod {
name: string
signature: string
}
45 changes: 35 additions & 10 deletions fixtures/output/type.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,43 +9,68 @@ export type ComplexUnionIntersection =
& {
metadata: Record<string, unknown>
}
export declare type ReadonlyDeep<T> = {


export type ReadonlyDeep<T> = {
readonly [P in keyof T]: T[P] extends object ? ReadonlyDeep<T[P]> : T[P]
}
export declare type ConditionalResponse<T> = T extends Array<infer U>

export type ConditionalResponse<T> = T extends Array<infer U>
? ApiResponse<U[]>
: T extends object
? ApiResponse<T>
: ApiResponse<string>
export declare type EventType = 'click' | 'focus' | 'blur'

export type EventType = 'click' | 'focus' | 'blur'
export type ElementType = 'button' | 'input' | 'form'
export declare type EventHandler = `on${Capitalize<EventType>}${Capitalize<ElementType>}`
export type EventHandler = `on${Capitalize<EventType>}${Capitalize<ElementType>}`

export type RecursiveObject = {
id: string
children?: RecursiveObject[]
parent?: RecursiveObject
metadata: Record<string, unknown>
}
export declare type UserId = string & { readonly __brand: unique symbol }

export type UserId = string & { readonly __brand: unique symbol }
export type ProductId = number & {
readonly __brand: unique symbol
}
export declare type DeepPartial<T> = T extends object ? {

export type DeepPartial<T> = T extends object ? {
[P in keyof T]?: DeepPartial<T[P]>
} : T
export declare type DeepRequired<T> = T extends object ? {

export type DeepRequired<T> = T extends object ? {
[P in keyof T]-?: DeepRequired<T[P]>
} : T
export declare type PolymorphicComponent<P = {}> = {

export type PolymorphicComponent<P = {}> = {
<C extends React.ElementType>(
props: { as?: C } & Omit<React.ComponentPropsWithRef<C>, keyof P> & P
): React.ReactElement | null
}
export declare type DynamicRecord<K extends PropertyKey> = {

export type DynamicRecord<K extends PropertyKey> = {
[P in K]: P extends number
? Array<unknown>
: P extends string
? Record<string, unknown>
: never
}
}

export type RecordMerge<T, U> = IsEmptyType<U> extends true
? T
: [T, U] extends [any[], any[]]
? U
: [T, U] extends [object, object]
? {
[K in keyof T | keyof U]: K extends keyof T
? K extends keyof U
? RecordMerge<T[K], U[K]>
: T[K]
: K extends keyof U
? U[K]
: never
}
: U
63 changes: 46 additions & 17 deletions src/extract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1142,7 +1142,6 @@ function isDeclarationStart(line: string): boolean {
|| trimmed.startsWith('function ')
|| trimmed.startsWith('async function ')
|| trimmed.startsWith('declare ')
|| trimmed.startsWith('declare module')
|| /^export\s+(?:interface|type|const|function\*?|async\s+function\*?)/.test(trimmed)
)
}
Expand Down Expand Up @@ -1925,22 +1924,52 @@ function processSourceFile(content: string, state: ProcessingState): void {
bracketDepth += openCurly - closeCurly
angleDepth += openAngle - closeAngle

// Check for end of declaration
const isComplete = bracketDepth === 0 && angleDepth === 0 && trimmedLine.endsWith('}')

// Look ahead for continuation
const nextLine = i < lines.length - 1 ? lines[i + 1]?.trim() : ''
const shouldContinue = bracketDepth > 0 || angleDepth > 0
|| (nextLine && !nextLine.startsWith('export') && !nextLine.startsWith('interface'))

if (!shouldContinue || isComplete) {
debugLog('declaration-complete', `Declaration complete at line ${i + 1}`)
processBlock(currentBlock, currentComments, state)
currentBlock = []
currentComments = []
inDeclaration = false
bracketDepth = 0
angleDepth = 0
// Special handling for type declarations
const isTypeDeclaration = currentBlock[0].trim().startsWith('type')
|| currentBlock[0].trim().startsWith('export type')

if (isTypeDeclaration) {
// For type declarations, we need to track the complete expression
const nextLine = i < lines.length - 1 ? lines[i + 1]?.trim() : ''
const shouldContinue = bracketDepth > 0 || angleDepth > 0
|| !trimmedLine.endsWith(';') // No semicolon yet
|| trimmedLine.endsWith('?') // Conditional type continues
|| trimmedLine.endsWith(':') // Property type continues
|| (nextLine && (
nextLine.startsWith('?')
|| nextLine.startsWith(':')
|| nextLine.startsWith('|')
|| nextLine.startsWith('&')
|| nextLine.startsWith('extends')
|| nextLine.startsWith('=>')
))

if (!shouldContinue) {
debugLog('declaration-complete', `Type declaration complete at line ${i + 1}`)
processBlock(currentBlock, currentComments, state)
currentBlock = []
currentComments = []
inDeclaration = false
bracketDepth = 0
angleDepth = 0
}
}
else {
// Original handling for non-type declarations
const isComplete = bracketDepth === 0 && angleDepth === 0 && trimmedLine.endsWith('}')
const nextLine = i < lines.length - 1 ? lines[i + 1]?.trim() : ''
const shouldContinue = bracketDepth > 0 || angleDepth > 0
|| (nextLine && !nextLine.startsWith('export') && !nextLine.startsWith('interface'))

if (!shouldContinue || isComplete) {
debugLog('declaration-complete', `Declaration complete at line ${i + 1}`)
processBlock(currentBlock, currentComments, state)
currentBlock = []
currentComments = []
inDeclaration = false
bracketDepth = 0
angleDepth = 0
}
}
}
}
Expand Down

0 comments on commit e23f56b

Please sign in to comment.