Skip to content

Large TS types cause type inference slowdown #166

@chenglou

Description

@chenglou

Hey! This isn't a big problem, but I'm putting the TS type checking speed diagnostics from Claude here in case some parts of the definitions can be simplified:

  Biggest type producers:                                                                                                                                                                                                                                                                 
  1. sury — 63,313 types (you use it for schemas)                                                                                                                                                                                                                                         

[...]

⏺ Found the issue. Looking at sury type definitions:                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                          
  The type explosion comes from:                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                          
  1. Recursive conditional types (UnknownToOutput, UnknownToInput) that traverse nested object structures:                                                                                                                                                                                
  export type UnknownToOutput<T> = T extends Schema<unknown>                                                                                                                                                                                                                              
    ? Output<T>                                                                                                                                                                                                                                                                           
    : T extends unknown[]                                                                                                                                                                                                                                                                 
    ? { [K in keyof T]: UnknownToOutput<T[K]> }  // recursive                                                                                                                                                                                                                             
    : T extends { [k in keyof T]: unknown }                                                                                                                                                                                                                                               
    ? Flatten<{                                                                                                                                                                                                                                                                           
        [k in keyof T as HasUndefined<...> extends true ? k : never]?: ...                                                                                                                                                                                                                
      } & { ... }>  // conditional mapped type                                                                                                                                                                                                                                            
    : T;                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                          
  2. Large discriminated union in Schema<Output, Input> — 14 variants (never, unknown, string, number, bigint, boolean, symbol, null, undefined, nan, function, instance, array, object, union)                                                                                           
  3. Recursive tuple transformers (_RestToOutput, _RestToInput) that build up arrays type-by-type
  
  Every time you write S.Output<typeof someSchema>, TypeScript:                                                                                                                                                                                                                           
  - Infers the schema structure                                                                                                                                                                                                                                                           
  - Traverses every field recursively                                                                                                                                                                                                                                                     
  - Evaluates HasUndefined conditionals for each field                                                                                                                                                                                                                                    
  - Computes the mapped type with optional/required splits                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                          
  With 138 usages of S.Output<> across your codebase and nested schemas, this compounds quickly → 63k types.                                                                                                                                                                              
                                                                                                                                                                                         

Seems this isn't very avoidable? If not, feel free to close!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions