From Closed SDKs to Open Types: Contributing Type Definitions for Popular AI/Mapping SDKs
typescontributionsdk

From Closed SDKs to Open Types: Contributing Type Definitions for Popular AI/Mapping SDKs

UUnknown
2026-02-14
9 min read
Advertisement

Practical guide (2026) to contribute TypeScript types for AI, mapping, and ClickHouse SDKs—Decide DT or first-party, write robust d.ts, test with tsd, and submit PRs.

Ship safer SDK integrations: close the typing gap for closed or poorly-typed SDKs

If your team spends hours troubleshooting runtime errors after integrating a mapping SDK, a ClickHouse client, or an AI mobile assistant, you’re fighting a preventable war. In 2026 the ecosystem has more closed-source and binary SDKs than ever—AI SDKs tied to large LLM providers, native mobile assistants, and high-performance DB clients like ClickHouse are booming—and many ship without first-class TypeScript types. That gap slows onboarding, increases bugs, and raises technical debt.

Why contributing type definitions matters in 2026

TypeScript adoption is mainstream across frontend, backend, and edge environments. Teams expect autocompletion, safer refactors, and compile-time guardrails. Contributing types—either via DefinitelyTyped or by adding first-party declarations—reduces friction for TypeScript adopters and increases an SDK’s adoption velocity.

Recent trends make this especially urgent:

  • Apple using Google’s Gemini tech continues to reshape assistant integration patterns, creating closed or rapidly-evolving client APIs that need typed surfaces.
  • Databases like ClickHouse became core OLAP engines for analytics teams after large investments and growth in 2025–2026; typed clients speed production usage and safer query composition.
  • Mapping SDKs (mobile or web) are often distributed as minified binaries or closed SDKs—typing them externally helps teams integrate complex event systems and callbacks without guessing shapes. For offline and local-first mapping workflows, see Local‑First Edge Tools for Pop‑Ups and Offline Workflows.

Decide: DefinitelyTyped or first-party types?

Start by asking three questions:

  1. Is the SDK actively maintained and open to PRs? If yes, prefer first-party types in the repository (index.d.ts or types field).
  2. Does the package already publish types under @types/ on npm? If not and upstream is closed/offline, DefinitelyTyped is a fast community route.
  3. Are you comfortable maintaining the types? DefinitelyTyped moves community maintenance to the repo; first-party types typically stay with the vendor.

Tradeoffs at a glance:

  • First-party types: better alignment with versioning, fewer compatibility hoops, and greater visibility to users. Requires collaboration with maintainers and matching license compatibility.
  • DefinitelyTyped: quick to publish types for closed or slow-moving packages. Community-driven, but you must follow DefinitelyTyped rules and keep a separate package under @types/.

Preparation checklist: what to gather before you type

  • Official SDK docs, changelogs, and JavaScript examples.
  • Runtime artifacts: UMD bundles, minified bundles, or native SDK headers (for mobile).
  • API surface map: constructors, factory functions, classes, events, callback signatures, and streaming endpoints.
  • Test samples from real apps, if available—these help validate edge cases.
  • Licensing and contribution policy to choose DefinitelyTyped or upstream. When in doubt about legal and licensing impacts, consult a technical legal audit guide like How to Audit Your Legal Tech Stack.

Tooling & workflow: what actually ships typed code

Use a lightweight, repeatable workflow so you can test types across TypeScript versions and CI. Typical toolset:

  • TypeScript (install multiple versions for CI matrix)
  • tsd for writing assertion tests (preferred today for many projects)
  • dtslint historically used by DefinitelyTyped—check the current DT contribution guide for the latest requirement.
  • types-publisher (for DefinitelyTyped contributions)
  • CI (GitHub Actions) to run tsc and tsd across versions — consider automating CI/CD security and maintenance steps similar to pipeline automation writeups like Automating Virtual Patching: Integrating 0patch-like Solutions into CI/CD.

Example minimal test setup (package.json snippets):

{
  "devDependencies": {
    "typescript": "^5.5.0",
    "tsd": "^0.26.0"
  },
  "scripts": {
    "test:types": "tsd"
  }
}

Patterns for robust, maintainable type definitions

When typing an SDK, focus on stable, minimal contracts first—users value autocompletion and safe defaults. Use these patterns:

  • Prefer explicit interfaces for public options and models; they’re extensible.
  • Use generics for typed responses (e.g., Client.query<Row>()).
  • Model events with strongly-typed overloads or discriminated unions rather than loose any.
  • Fallbacks: when an SDK returns dynamic JSON, type as unknown and provide narrowing helpers.
  • Declaration merging is useful for adding global augmentation or plugin systems common in mapping SDKs.

Example: ClickHouse Node client (simplified)

ClickHouse clients often support typed query results and streaming. Here’s a compact declaration to get you started.

declare module "clickhouse-client" {
  export interface ClickHouseOptions {
    url: string;
    username?: string;
    password?: string;
    database?: string;
    timeout?: number;
  }

  export interface QueryResult> {
    rows: Row[];
    rowsAffected?: number;
  }

  export class ClickHouseClient {
    constructor(options: ClickHouseOptions);
    query>(sql: string, params?: any[]): Promise>;
    streamQuery>(sql: string, onRow: (row: Row) => void): Promise;
    close(): Promise;
  }

  export function createClient(options: ClickHouseOptions): ClickHouseClient;
}

Usage example that benefits from types:

import { createClient } from "clickhouse-client";
const client = createClient({ url: process.env.CLICKHOUSE_URL! });

interface EventRow { id: number; event_type: string; payload: any }
const res = await client.query("SELECT id, event_type, payload FROM events LIMIT 10");
res.rows.forEach(r => console.log(r.event_type));

Example: mapping SDK types (web SDK)

Mapping SDKs expose init options, map methods, and an event bus. Model events clearly to help integrations.

declare module "super-map-sdk" {
  export interface MapInitOptions {
    container: HTMLElement | string;
    center?: [number, number];
    zoom?: number;
    style?: string;
  }

  export type MapEvent =
    | { type: "click"; lngLat: [number, number]; target: string }
    | { type: "load" }
    | { type: "moveend" };

  export class Map {
    constructor(opts: MapInitOptions);
    on(event: MapEvent["type"], handler: (e: MapEvent) => void): void;
    addMarker(id: string, lngLat: [number, number]): void;
    removeMarker(id: string): void;
    getCenter(): [number, number];
  }

  export function createMap(opts: MapInitOptions): Map;
}

Example: mobile assistant / AI SDK (client-side)

AI or assistant SDKs often mix sync config, async streaming responses, and typed intents. Here’s a compact surface:

declare module "mobile-assistant-sdk" {
  export interface AssistantConfig {
    apiKey?: string;
    sessionId?: string;
    model?: string;
    locale?: string;
  }

  export type Intent = { name: string; confidence: number; slots?: Record };

  export interface AssistantResponse {
    text?: string;
    intent?: Intent;
    payload?: T;
    error?: { code: string; message: string };
  }

  export class AssistantClient {
    constructor(config: AssistantConfig);
    send(text: string): Promise>;
    stream(text: string, onChunk: (chunk: AssistantResponse) => void): Promise;
    on(event: "connected" | "disconnected" | "error", cb: (arg?: any) => void): void;
  }

  export function createAssistant(config: AssistantConfig): AssistantClient;
}

Testing types: tools and patterns

Type tests (not runtime tests) assert that your types produce the intended compile-time results. Use tsd to write tests like:

import { expectType } from "tsd";
import { createClient } from "clickhouse-client";

const client = createClient({ url: "http://localhost" });
expectType>(client.query("SELECT 1"));

Run tests across TypeScript versions in CI. Sample GitHub Action matrix:

strategy:
  matrix:
    ts: [4.9, 5.3, 5.6]
steps:
  - run: npm ci
  - run: npm run test:types # uses the local typescript version from the matrix

DefinitelyTyped contribution flow (practical steps)

  1. Fork the DefinitelyTyped repo and clone it locally.
  2. Create a folder under types/ named after the npm package (e.g., clickhouse-client).
  3. Add an index.d.ts, tsconfig.json, and tsd-test.ts (the tests).
  4. Follow the repo lint rules—run npm run lint and npm test locally.
  5. Open a PR and provide real-world examples and migration notes in the description.

Note: DefinitelyTyped maintains strict review practices—explain assumptions and include test cases for edge behavior.

Working with SDK owners: ship first-party types

When the upstream maintainer is responsive, propose a small, incremental PR:

  • Start with minimal types for public API functions and the most-used classes.
  • Include usage examples in the README and a minimal test harness.
  • Offer to maintain initial patches, or propose a co-maintenance model via a types folder and MAP to semantic releases.

Pro tip: vendor adoption of type definitions increases install conversions. Show maintainers that types reduce their issue volume from TypeScript users.

Versioning, compatibility and maintenance

Types should follow the package’s semver. For DefinitelyTyped:

  • Publish one major version per breaking change.
  • Keep tests for historical TypeScript versions if the library supports them.

Automate maintenance with:

  • CI tests on PRs across TypeScript versions.
  • Dependabot for types devDeps.
  • A contributor guide inside the types folder explaining assumptions, versions covered, and test commands.

Practical PR checklist (copyable)

  • Include API surface in README examples.
  • Add index.d.ts with clear comments and credits.
  • Write tsd tests for critical patterns and edge cases.
  • Run a local lint and test suite across TS versions.
  • Document which runtime behaviors are not typed (e.g., dynamic JSON payloads).
  • Link to upstream docs and include version mapping.

Case studies & 2026 predictions

ClickHouse’s strong funding rounds in 2024–2025 pushed ClickHouse into more product stacks. Community-contributed types for ClickHouse clients shortened the path from PoC to production in several analytics teams. Similarly, after Apple’s integration choices for mobile assistants (leveraging Gemini technology) surfaced new closed SDK patterns, community type packages helped early adopters integrate assistant features without waiting for vendor types. For discussions comparing LLM behaviors and safety tradeoffs that influence how you model streaming responses, see analyses like Gemini vs Claude Cowork and vendor-specific writeups such as Siri + Gemini: What Developers Need to Know.

Predictions for the near future (2026):

  • SDKs that ship first-party TypeScript types will be preferred by enterprise buyers—typed SDKs reduce integration risk.
  • AI SDKs will push more streaming, typed event models; types that model partial responses and streaming chunks will be crucial.
  • DefinitelyTyped will remain vital for closed or slow-to-ship vendors, but more vendors will accept PRs for first-party types to control developer experience.

Final actionable takeaways

  • Start small: type the most-used functions and add tests—don’t try to type every private edge case in the first PR.
  • Use tsd: write assertion tests and run them across a TypeScript-version matrix in CI.
  • Prefer first-party when possible: submit a minimal PR to upstream and explain the user benefits (fewer issues, better DX).
  • Submit to DefinitelyTyped: when upstream is closed or unresponsive; follow the repo’s lint and test rules.
  • Document assumptions: state runtime behaviors you could not verify (e.g., dynamic JSON) so users understand typing boundaries.

Where to go next

If you want a template to get started, clone a community starter repo (search for @types/starter) or use the examples above to scaffold an index.d.ts, tests, and CI. Contributing types is high-leverage: a small PR can unblock dozens of teams and reduce runtime errors across production stacks.

Want a hand? Help the ecosystem—pick one of these next steps:

  • Open a GitHub issue on an SDK requesting types and propose a minimal PR.
  • Fork DefinitelyTyped and practice by creating types for a small client you use daily (mapping SDK, ClickHouse client, or AI SDK).
  • Share your PR in the TypeScript community channels and ask for a quick review—people want to help improve type coverage.

Ready to contribute? Start by forking a repo and submitting a tiny PR that types one function. You’ll earn gratitude from hundreds of TypeScript users and dramatically reduce integration risk for your team.

Call to action: Pick an SDK you use this week—open the repo or DefinitelyTyped, add a minimal index.d.ts, write a tsd test, and open a PR. If you prefer guided help, consider hiring a TypeScript consultant to write first-party types and automate maintenance. Start today and make the integration pain stop for everyone.

Advertisement

Related Topics

#types#contribution#sdk
U

Unknown

Contributor

Senior editor and content strategist. Writing about technology, design, and the future of digital media. Follow along for deep dives into the industry's moving parts.

Advertisement
2026-02-16T17:40:29.212Z