---
title: Twoslash
description: Use Typescript Twoslash in your docs
---

## Usage

Thanks to the Twoslash integration of [Shiki](https://github.com/shikijs/shiki), the default code syntax highlighter, it is as simple as adding a transformer.

```package-install
fumadocs-twoslash
```

Add to your Shiki transformers.

<Callout title='Example for Fumadocs MDX'>

```ts twoslash title="source.config.ts"
import { defineConfig } from 'fumadocs-mdx/config';
import { transformerTwoslash } from 'fumadocs-twoslash';
import { rehypeCodeDefaultOptions } from 'fumadocs-core/mdx-plugins';

export default defineConfig({
  mdxOptions: {
    rehypeCodeOptions: {
      transformers: [
        ...(rehypeCodeDefaultOptions.transformers ?? []),
        transformerTwoslash(),
      ],
    },
  },
});
```

</Callout>

Add required styles and components, note that you have to configure Tailwind CSS and the official Tailwind CSS plugin first.

```tsx title="layout.tsx"
import 'fumadocs-twoslash/twoslash.css';
```

```tsx title="page.tsx"
import { Popup, PopupContent, PopupTrigger } from 'fumadocs-twoslash/ui';
import defaultMdxComponents from 'fumadocs-ui/mdx';

<MDX
  components={{
    ...defaultMdxComponents,
    Popup,
    PopupContent,
    PopupTrigger,
  }}
/>;
```

Now you can add `twoslash` meta string to codeblocks.

````md
```ts twoslash
console.log('Hello World');
```
````

### Example

Learn more about [Twoslash notations](https://twoslash.netlify.app/refs/notations).

```ts twoslash title="Test"
type Player = {
  /**
   * The player name
   * @default 'user'
   */
  name: string;
};

// ---cut---
// @noErrors
console.g;
//       ^|

// ---cut-start---
// ---cut-end---

// ---cut-start---
// ---cut-end---

// ---cut-start---
// ---cut-end---

// ---cut-start---
// ---cut-end---

const player: Player = { name: 'Hello World' };
//    ^?
```

```ts twoslash
const a = '123';

console.log(a);
//      ^^^
```

```ts twoslash
import { generateFiles } from 'fumadocs-openapi';

void generateFiles({
  input: ['./museum.yaml'],
  output: './content/docs/ui',
});
```

```ts twoslash
// @errors: 2588
const a = '123';

a = 132;
```

### Using on Runtime

To use it on Next.js runtime, add `typescript` and `twoslash` to `serverExternalPackages`:

```ts title="next.config.mjs"
import { createMDX } from 'fumadocs-mdx/next';

const withMDX = createMDX();

/** @type {import('next').NextConfig} */
const config = {
  reactStrictMode: true,
  serverExternalPackages: ['twoslash', 'typescript'],
};

export default withMDX(config);
```

Install the external dependencies:

```package-install
typescript twoslash
```

Pass the transformer to Shiki, see https://shiki.style/packages/next for details.

```tsx twoslash
import React from 'react';
import { CodeBlock, Pre } from 'fumadocs-ui/components/codeblock';
import { createStyleTransformer } from 'fumadocs-core/server';
import { transformerTwoslash } from 'fumadocs-twoslash';
import { Popup, PopupContent, PopupTrigger } from 'fumadocs-twoslash/ui';
import { getSingletonHighlighter, bundledLanguages } from 'shiki';
import { toJsxRuntime } from 'hast-util-to-jsx-runtime';
import { Fragment, jsx, jsxs } from 'react/jsx-runtime';

export async function Code({
  code,
  lang = 'ts',
}: {
  lang?: string;
  code: string;
}) {
  const highlighter = await getSingletonHighlighter({
    langs: Object.keys(bundledLanguages),
    themes: ['vesper'],
  });

  const hast = highlighter.codeToHast(code, {
    lang,
    themes: {
      light: 'vesper',
      dark: 'vesper',
    },
    defaultColor: false,
    transformers: [
      createStyleTransformer(),
      transformerTwoslash({
        explicitTrigger: false,
      }),
    ],
  });

  const rendered = toJsxRuntime(hast, {
    Fragment,
    jsx,
    jsxs,
    development: false,
    components: {
      pre: (props) => (
        <CodeBlock {...props}>
          <Pre>{props.children}</Pre>
        </CodeBlock>
      ),
      Popup,
      PopupContent,
      PopupTrigger,
    },
  });

  return rendered;
}
```
