Skip to main content
Complete TypeScript type definitions for the yt-dlp-ejs solver API, extracted from the source code.

Core Types

Input

The input type for the main solver function. It’s a discriminated union with two variants.
type Input =
  | {
      type: "player";
      player: string;
      requests: Request[];
      output_preprocessed: boolean;
    }
  | {
      type: "preprocessed";
      preprocessed_player: string;
      requests: Request[];
    };

Output

The output type returned by the main solver function. It’s a discriminated union representing success or failure.
type Output =
  | {
      type: "result";
      preprocessed_player?: string;
      responses: Response[];
    }
  | {
      type: "error";
      error: string;
    };

Request

Represents a single challenge request for solving.
type Request = {
  type: "n" | "sig";
  challenges: string[];
};
type
'n' | 'sig'
required
Type of challenge to solve:
  • "n": N-parameter (throttling parameter) challenge
  • "sig": Signature challenge
challenges
string[]
required
Array of challenge strings to solve. Each string will be processed by the corresponding solver function.

Example

// N-parameter request
const nRequest: Request = {
  type: "n",
  challenges: [
    "0g0sn1Oa_LVlQ",
    "Xnp1r9qNu4c3b"
  ]
};

// Signature request
const sigRequest: Request = {
  type: "sig",
  challenges: [
    "A1B2C3D4E5F6G7H8I9J0"
  ]
};

// Multiple requests in one call
const input: Input = {
  type: "player",
  player: playerCode,
  requests: [nRequest, sigRequest],
  output_preprocessed: false
};

Response

Represents the result of processing a single Request. It’s a discriminated union.
type Response =
  | {
      type: "result";
      data: Record<string, string>;
    }
  | {
      type: "error";
      error: string;
    };

Utility Types

DeepPartial

Utility type for creating deeply partial versions of types. Used internally for configuration and validation.
type DP<T> = T extends (infer U)[]
  ? DeepPartial<U>[]
  : T extends object
    ? { [P in keyof T]?: DeepPartial<T[P]> }
    : T;

type ValueOf<T> = T extends (infer U)[]
  ? U
  : T extends object
    ? T[keyof T]
    : never;

export type DeepPartial<T> =
  | DP<T>
  | { or: DP<T>[] }
  | { anykey: DP<ValueOf<T>>[] };
This is an advanced utility type used internally. Most users won’t need to use it directly.

Type Guards

Helper functions for working with discriminated unions.

Checking Output Type

function isResultOutput(output: Output): output is Extract<Output, { type: "result" }> {
  return output.type === "result";
}

function isErrorOutput(output: Output): output is Extract<Output, { type: "error" }> {
  return output.type === "error";
}

// Usage
const output = main(input);

if (isResultOutput(output)) {
  // TypeScript knows output.responses exists
  console.log(output.responses);
} else {
  // TypeScript knows output.error exists
  console.error(output.error);
}

Checking Response Type

function isResultResponse(response: Response): response is Extract<Response, { type: "result" }> {
  return response.type === "result";
}

function isErrorResponse(response: Response): response is Extract<Response, { type: "error" }> {
  return response.type === "error";
}

// Usage
if (isResultOutput(output)) {
  output.responses.forEach(response => {
    if (isResultResponse(response)) {
      console.log("Solved challenges:", response.data);
    } else {
      console.error("Request failed:", response.error);
    }
  });
}

Complete Type Example

Here’s a complete example demonstrating all types in use:
import type { Input, Output, Request, Response } from './yt/solver/main';
import main from './yt/solver/main';

// Define requests
const nRequest: Request = {
  type: "n",
  challenges: ["challenge1", "challenge2"]
};

const sigRequest: Request = {
  type: "sig",
  challenges: ["signature1"]
};

// Create input
const input: Input = {
  type: "player",
  player: rawPlayerCode,
  requests: [nRequest, sigRequest],
  output_preprocessed: true
};

// Get output
const output: Output = main(input);

// Handle output
if (output.type === "error") {
  console.error("Top-level error:", output.error);
  process.exit(1);
}

// Save preprocessed player for future use
if (output.preprocessed_player) {
  saveToCache(output.preprocessed_player);
}

// Process each response
output.responses.forEach((response: Response, index: number) => {
  const request = input.requests[index];
  
  if (response.type === "error") {
    console.error(`Request ${request.type} failed:`, response.error);
    return;
  }
  
  // response.data is Record<string, string>
  Object.entries(response.data).forEach(([challenge, solved]) => {
    console.log(`${request.type} - ${challenge}: ${solved}`);
  });
});

TypeScript Configuration

For best type inference, ensure your tsconfig.json includes:
{
  "compilerOptions": {
    "strict": true,
    "strictNullChecks": true,
    "noImplicitAny": true,
    "moduleResolution": "node",
    "esModuleInterop": true
  }
}
The discriminated unions (Input, Output, Response) provide excellent type narrowing when using TypeScript’s control flow analysis.

Build docs developers (and LLMs) love