Bun TypeScript 支持 #

概述 #

Bun 原生支持 TypeScript,无需额外配置即可直接运行 .ts 文件。Bun 内置了 TypeScript 转译器,可以快速编译 TypeScript 代码。

快速开始 #

直接运行 TypeScript #

typescript
// index.ts
interface User {
  name: string;
  age: number;
}

const user: User = {
  name: "Bun",
  age: 3,
};

console.log(`Hello, ${user.name}!`);
bash
# 直接运行,无需编译
bun run index.ts

安装类型定义 #

bash
# 安装 Bun 类型
bun add -d bun-types

# 安装 Node.js 类型(兼容层)
bun add -d @types/node

tsconfig.json #

基本配置 #

json
{
  "compilerOptions": {
    "target": "ESNext",
    "module": "ESNext",
    "moduleResolution": "bundler",
    "lib": ["ESNext"],
    "strict": true,
    "skipLibCheck": true,
    "noEmit": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "forceConsistentCasingInFileNames": true,
    "resolveJsonModule": true,
    "isolatedModules": true
  },
  "include": ["src/**/*", "index.ts"],
  "exclude": ["node_modules"]
}

Bun 推荐配置 #

json
{
  "compilerOptions": {
    "target": "ESNext",
    "module": "ESNext",
    "moduleResolution": "bundler",
    "lib": ["ESNext"],
    "types": ["bun-types"],
    "strict": true,
    "skipLibCheck": true,
    "noEmit": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "forceConsistentCasingInFileNames": true,
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "react-jsx",
    "jsxImportSource": "react",
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"]
    }
  },
  "include": ["src/**/*", "*.ts"],
  "exclude": ["node_modules", "dist"]
}

配置选项说明 #

选项 说明 推荐值
target 编译目标 ESNext
module 模块系统 ESNext
moduleResolution 模块解析策略 bundler
strict 严格模式 true
skipLibCheck 跳过库检查 true
noEmit 不输出文件 true
jsx JSX 转换 react-jsx

类型系统 #

基本类型 #

typescript
// 原始类型
const name: string = "Bun";
const version: number = 1.2;
const isFast: boolean = true;

// 数组
const numbers: number[] = [1, 2, 3];
const names: Array<string> = ["a", "b", "c"];

// 元组
const tuple: [string, number] = ["Bun", 1];

// 对象
const obj: { name: string; age: number } = {
  name: "Bun",
  age: 3,
};

// any 和 unknown
let anything: any = "anything";
let safe: unknown = "safe";

接口 #

typescript
interface User {
  id: number;
  name: string;
  email: string;
  age?: number;  // 可选属性
  readonly createdAt: Date;  // 只读属性
}

interface Admin extends User {
  role: "admin";
  permissions: string[];
}

const user: User = {
  id: 1,
  name: "Bun",
  email: "bun@example.com",
  createdAt: new Date(),
};

类型别名 #

typescript
type ID = string | number;

type Status = "pending" | "active" | "inactive";

type User = {
  id: ID;
  name: string;
  status: Status;
};

type Point = {
  x: number;
  y: number;
};

type Vector = Point & {
  z: number;
};

泛型 #

typescript
// 泛型函数
function identity<T>(arg: T): T {
  return arg;
}

const str = identity<string>("hello");
const num = identity(42);  // 类型推断

// 泛型接口
interface Response<T> {
  data: T;
  status: number;
  message: string;
}

// 泛型类
class Container<T> {
  private value: T;

  constructor(value: T) {
    this.value = value;
  }

  getValue(): T {
    return this.value;
  }
}

// 泛型约束
interface Lengthwise {
  length: number;
}

function logLength<T extends Lengthwise>(arg: T): T {
  console.log(arg.length);
  return arg;
}

联合类型与交叉类型 #

typescript
// 联合类型
type StringOrNumber = string | number;

function format(input: StringOrNumber): string {
  if (typeof input === "string") {
    return input;
  }
  return input.toString();
}

// 交叉类型
type Name = { name: string };
type Age = { age: number };
type Person = Name & Age;

const person: Person = {
  name: "Bun",
  age: 3,
};

// 类型守卫
function isString(value: unknown): value is string {
  return typeof value === "string";
}

路径映射 #

配置路径别名 #

json
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"],
      "@components/*": ["./src/components/*"],
      "@utils/*": ["./src/utils/*"],
      "@types/*": ["./src/types/*"]
    }
  }
}

使用路径别名 #

typescript
// 不使用别名
import { Button } from "../../../components/Button";
import { formatDate } from "../../../utils/format";

// 使用别名
import { Button } from "@/components/Button";
import { formatDate } from "@utils/format";

Bun 配置 #

bunfig.toml 中配置:

toml
[run]
# Bun 自动读取 tsconfig.json 的路径映射

类型声明 #

声明文件 #

typescript
// types/global.d.ts
declare global {
  interface Window {
    customProperty: string;
  }

  var globalVar: number;
}

export {};

// types/module.d.ts
declare module "my-module" {
  export function doSomething(): void;
  export const version: string;
}

模块扩展 #

typescript
// 扩展现有模块
declare module "express" {
  interface Request {
    user?: {
      id: string;
      name: string;
    };
  }
}

环境声明 #

typescript
// env.d.ts
interface ImportMetaEnv {
  readonly VITE_API_URL: string;
  readonly NODE_ENV: string;
}

interface ImportMeta {
  readonly env: ImportMetaEnv;
}

类型工具 #

工具类型 #

typescript
// Partial - 所有属性可选
type PartialUser = Partial<User>;

// Required - 所有属性必需
type RequiredUser = Required<User>;

// Pick - 选择属性
type UserName = Pick<User, "id" | "name">;

// Omit - 排除属性
type UserWithoutEmail = Omit<User, "email">;

// Record - 记录类型
type UserMap = Record<string, User>;

// ReturnType - 返回类型
function getUser() {
  return { id: 1, name: "Bun" };
}
type User = ReturnType<typeof getUser>;

// Parameters - 参数类型
type UserParams = Parameters<typeof getUser>;

// NonNullable - 排除 null 和 undefined
type NonNullableString = NonNullable<string | null | undefined>;

条件类型 #

typescript
// 条件类型
type IsString<T> = T extends string ? true : false;

type A = IsString<string>;  // true
type B = IsString<number>;  // false

// infer 关键字
type UnwrapPromise<T> = T extends Promise<infer U> ? U : T;

type Result = UnwrapPromise<Promise<string>>;  // string

映射类型 #

typescript
// 映射类型
type Readonly<T> = {
  readonly [P in keyof T]: T[P];
};

type Mutable<T> = {
  -readonly [P in keyof T]: T[P];
};

type Optional<T> = {
  [P in keyof T]?: T[P];
};

// 使用
interface User {
  name: string;
  age: number;
}

type ReadonlyUser = Readonly<User>;
type OptionalUser = Optional<User>;

类型检查 #

运行时检查 #

Bun 本身不进行类型检查,只进行转译。需要使用 tsc 进行类型检查:

bash
# 安装 TypeScript
bun add -d typescript

# 类型检查
bunx tsc --noEmit

# 添加到 package.json
{
  "scripts": {
    "typecheck": "tsc --noEmit"
  }
}

类型检查脚本 #

typescript
// scripts/typecheck.ts
import { $ } from "bun";

try {
  await $`tsc --noEmit`;
  console.log("✅ Type check passed!");
} catch (error) {
  console.error("❌ Type check failed!");
  process.exit(1);
}

类型断言 #

typescript
// 类型断言
const value: unknown = "hello";
const str = value as string;

// 双重断言(不推荐)
const num = value as unknown as number;

// const 断言
const config = {
  name: "Bun",
  version: 1.2,
} as const;
// { readonly name: "Bun"; readonly version: 1.2 }

// 非空断言
const element = document.getElementById("app")!;

JSX 类型支持 #

React 类型 #

typescript
// 安装类型
bun add -d @types/react @types/react-dom

// 使用
import { useState, useEffect } from "react";

function Counter(): JSX.Element {
  const [count, setCount] = useState<number>(0);
  return <button onClick={() => setCount(c => c + 1)}>{count}</button>;
}

自定义 JSX 类型 #

typescript
// types/jsx.d.ts
declare global {
  namespace JSX {
    interface IntrinsicElements {
      "my-custom-element": {
        customProp?: string;
      };
    }
  }
}

最佳实践 #

项目结构 #

text
src/
├── index.ts
├── types/
│   ├── index.ts       # 导出所有类型
│   ├── user.ts
│   ├── product.ts
│   └── api.ts
├── services/
│   ├── user.ts
│   └── product.ts
└── utils/
    ├── index.ts
    └── helpers.ts

类型组织 #

typescript
// types/index.ts
export * from "./user";
export * from "./product";
export * from "./api";

// types/user.ts
export interface User {
  id: string;
  name: string;
  email: string;
}

export type UserCreateInput = Omit<User, "id">;
export type UserUpdateInput = Partial<UserCreateInput>;

export interface UserResponse {
  success: boolean;
  data?: User;
  error?: string;
}

严格模式 #

json
{
  "compilerOptions": {
    "strict": true,
    "noUncheckedIndexedAccess": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "exactOptionalPropertyTypes": true
  }
}

类型导入优化 #

typescript
// 使用 type 关键字明确类型导入
import type { User, Product } from "./types";
import { UserService } from "./services";

// 内联类型导入
import { UserService, type User } from "./services";

常见问题 #

模块解析问题 #

typescript
// 问题:找不到模块
import { something } from "./utils";

// 解决:确保扩展名正确或配置 paths
import { something } from "./utils/index.ts";

类型扩展问题 #

typescript
// 问题:类型扩展不生效
// 解决:确保声明文件被包含
// tsconfig.json
{
  "include": ["src/**/*", "types/**/*"]
}

第三方库类型 #

bash
# 安装类型定义
bun add -d @types/express
bun add -d @types/lodash

# 或使用 DefinitelyTyped
bun add -d @types/node

下一步 #

现在你已经了解了 Bun 的 TypeScript 支持,接下来学习 JSX 支持 深入了解 Bun 的 JSX 转换功能。

最后更新:2026-03-29