---
title: "Interop in both directions"
image: "https://hem.run/social/hem.png"
---

> Documentation Index
> Fetch the complete documentation index at: https://hem.run/llms.txt
> Use this file to discover all available pages before exploring further.

# Interop in both directions

Importing typed TS needs nothing:

```hem
import { drizzle } from "drizzle-orm/d1"
import { desc } from "drizzle-orm"

let recent = (db: DrizzleD1Database) =>
  db.select().from(scans).orderBy(desc(scans.createdAt.getSQL())).limit(20)
```

Tagged templates pass through too: `` sql`select * from users where id = ${id}` `` works with any tagged-template library. When a dependency produces untyped values, Hem prevents `any` from propagating: any expression whose checked type is `any` is treated as `unknown`. The compiler inserts the cast in the emitted code and your editor shows a hint at the site. `unknown` is unusable until you narrow it with `match`, `typeof`, or `instanceof`, so `any` never propagates into a Hem program; it is automatically converted to `unknown` at the boundary.

Conversely, a `.ts` file imports a `.hem` module and sees ordinary functions, unions, and constants: §7's emit is the ABI. `export default` is supported (such as for React Router routes); ESM only.

Delegated TypeScript types are layout-invariant. Conditional branches and structural unions may stay compact or break before `?`, `:`, `|`, or `&`; the formatter preserves either valid spelling, and both emit the same declaration shape. TypeScript still owns validation of the opaque type extent, while Hem maps any diagnostic back to the authored span.

Framework module directives are ordinary double-quoted prologue strings and stay the first executable statements in emitted TypeScript:

```hem
"use client"

import { useState } from "react"
```

Hem preserves a contiguous top-of-file string prologue, including `"use client"`, `"use server"`, and platform directives such as `"use strict"`. A React directive after an import, declaration, or executable statement is HEM2024 rather than an inert discarded string. Function-body directive prologues and non-string directive syntaxes are intentionally unsupported; keep those uncommon boundaries in TypeScript.

Source: https://hem.run/tour/interop-in-both-directions/index.mdx
