Skip to content
LogoLogo

TypeScript Interop

Adopt VibeLang without leaving the JavaScript ecosystem

Imported .ts and .js modules keep their host behavior. A .vibe file opts into must-use Results, Optional lifting, Promise-chain restrictions, capability inference, and other VibeLang semantics.

Type-Only Imports

import type { User } from "./legacy-types"

An erased import adds no runtime requirement. Runtime use of imported TypeScript or JavaScript adds the built-in TypeScript requirement when the implementation is not portable.

Exact Host Modules

import { readFile } from "node:fs/promises"
 
// contributes Module<"node:fs/promises">

Native-pinned code can reject that requirement. Application code should usually depend on a portable FileSystem capability instead.

Dynamic Features

any, eval, unconstrained reflection, Promise subclassing, and custom thenables may require the TypeScript runtime or be forbidden on stricter targets. The complete portability table remains specification work.

Adapt a Throwing Boundary

class ConnectFailed extends Error {
  constructor(options: { cause: unknown }) {
    super("Connection failed", options)
  }
}
 
function connect(options: Options): Result<Client, ConnectFailed> {
  return Result.try(
    () => legacyConnect(options),
    cause => new ConnectFailed({ cause }),
  )
}

Result.try converts a foreign exception to a stable Error contract. Without a mapper it uses UnhandledException.

Adapt a Rejecting Promise

async function fetchUser(
  id: string,
): Promise<Result<User, RequestFailed>> {
  return await Result.tryPromise(
    () => legacyFetchUser(id),
    cause => new RequestFailed({ cause }),
  )
}

Authored VibeLang consumes Promises with await, never instance .then, .catch, or .finally. Imported code may use them internally.

Nullable Boundaries

const user = Optional.fromNullable(legacyLookup(id))
legacyConsume(user.toNullable())

VibeLang does not reinterpret TypeScript optional properties or null unions. Conversion is explicit at the boundary.

Effect Interop

A future bridge can map Effect<A, E, R> to functions returning Result<A, E> and using Context requirements, and back again. This API is not yet stable.

Native Compatibility

Native output is a checked property of the complete dependency/provider graph, not a separate source dialect. Diagnostics should report the requirement path that prevents a native build.