外部(external)ガイド

原文: Externals guide ── © Louis Pilfold and the Gleam contributors, Apache-2.0。日本語訳 © 2026 Canonical。

注意

外部機能は控えめに使用してください。

常に Gleam ベースの解決策を優先し、外部機能を利用するのは、要件や開発上の制約を満たす代替手段が他にない場合のみにしてください。

外部とは何か

Gleam の外部型や外部関数を利用すると、Gleam コードから他言語のコードを呼び出せます。必要な機能を提供する純粋な Gleam ライブラリが見つからない場合の解決策になります。

利用可能な言語は、Gleam コードのコンパイルターゲットによって異なります。

  • Erlang 上の Gleam では、Erlang、Elixir、LFE、その他の BEAM 言語が使えます。
  • JavaScript 上の Gleam では、JavaScript、およびその他の JavaScript へコンパイルされる言語が使えます。

他言語の関数を呼び出しても、Gleam で書かれた関数を呼び出す場合と比べて追加のパフォーマンスコストはかかりません。

外部をいつ使うか

外部機能は便利ですが、いくつかの欠点もあります。

  • 外部コードは Gleam コンパイラによる解析や型検査の対象外となるため、バグや実行時エラーの原因になりえます。
  • Gleam の言語サーバは他言語をサポートしていないため、外部コード記述時にはエディタの支援が制限されます。
  • 外部コードを含めると、Gleam プロジェクトを Erlang と JavaScript の両ターゲットで動作させることが困難、あるいは不可能になる場合があります。

外部機能の使用は最小限に留めることを推奨します。大半のプロジェクトではまったく必要ありませんが、次のような状況では有効な選択肢となります。

  • 利用中のランタイムが提供する API を呼び出す必要がある場合(例: 仮想マシンからメモリ使用量の統計を取得する)。
  • 目的の機能を実装した他言語のコードがすでに対象ランタイム上に存在し、予算や納期の制約から Gleam で再実装するのが現実的ではない場合。

このような場合でも、同じ機能を提供する既存の Gleam パッケージがないか確認してください。純粋な Gleam パッケージを使えば、より良い開発者体験を維持したまま問題を解決できる可能性があります。

もちろん、仕組みを学ぶためや、単に楽しむ目的で外部機能を利用しても構いません。

外部関数を定義する

外部関数とは、他言語で記述されて Gleam コードに取り込まれた関数のことで、通常の Gleam 関数と同じように呼び出せます。

外部関数は、@external 属性を付けた本体のない関数として定義します。この属性は 3 つの引数を取り、Gleam 以外の言語で書かれた関数の所在を指定します。

  • 外部関数の対象ターゲット。erlang または javascript のいずれかです。
  • その関数がエクスポートされているモジュール名。
  • その関数の名前。

たとえば、Erlang の lists モジュールから reverse 関数を取り込む外部関数は次のようになります。

@external(erlang, "lists", "reverse")
pub fn reverse_list(list: List(element)) -> List(element)

外部関数では型注釈を省略できず、必ず記述する必要があります。Gleam コンパイラは、その関数の使用箇所がすべて注釈された型に適合しているかを検証しますが、他言語の実装が指定した型を返すかどうかや、そもそもその関数が存在するかどうかは確認できません。外部関数を定義する際は、@external 属性と型注釈が正確であるよう細心の注意を払ってください。

そのため、外部関数を利用する場合は通常よりも多くの単体テストを書くことをおすすめします。

複数ターゲットの外部

外部関数は、その関数が実装されているターゲット向けにコンパイルする場合にのみ使用できます。たとえば、ある関数が JavaScript 向けの外部実装しか持たない場合、Erlang 向けにコンパイルされる Gleam コードでそれを使用しようとするとコンパイルエラーになります。

@external 属性は複数回指定できるため、外部関数に両方のターゲット向けの実装を提供し、常に利用可能な状態にすることも可能です。

@external(erlang, "lists", "reverse")
@external(javascript, "./project_ffi.mjs", "reverse_list")
pub fn reverse_list(list: List(element)) -> List(element)

Erlang 向けにコンパイルされた場合、この関数は Erlang の lists モジュールの reverse 関数を呼び出します。一方、JavaScript 向けにコンパイルされた場合は、project_ffi.mjs という JavaScript モジュールの reverse_list 関数を呼び出します。

Gleam のフォールバック

1 つの関数に対して、Gleam の実装と外部の実装を両方提供することもできます。現在のコンパイルターゲット向けの外部実装があればそれが優先され、なければ Gleam の実装が使われます。

これは、Gleam で実装可能な関数について、特定のターゲット向けにより最適化されたバージョンを用意したい場合に便利です。

@external(erlang, "lists", "reverse")
pub fn reverse_list(list: List(element)) -> List(element) {
  reverse_and_prepend(list, [])
}

Erlang 向けにコンパイルされた場合、この関数は Erlang の lists モジュールの reverse 関数になります。JavaScript 向けにコンパイルされた場合は Gleam の実装が採用され、reverse_and_prepend 関数が呼び出されます。

外部型を定義する

Gleam コードでは「外部型」機能を使用して、他言語で定義されたデータ型を利用できます。構文はカスタム型に似ていますが、バリアントを指定しない点が異なります。

pub type ErlangReference

ここでは ErlangReference という名前の外部型を定義しました。これは Erlang のreference() 型を表すために使用します。Gleam で使う名前は外部言語での名前と一致している必要はなく、自由に命名できます。

Gleam はこの型について、存在することと定義された名前以外は一切関知しないため、Gleam コード内で直接構築したり操作したりすることはできません。代わりに外部関数を使用する必要があります。

pub type ErlangReference

@external(erlang, "erlang", "make_ref")
pub fn make_reference() -> ErlangReference

make_reference という外部関数を定義して、リファレンスを構築できるようにしました。リファレンスを引数に取る関数も同様に定義できます。

なお、この例では Erlang のリファレンス型を使用していますが、実際の Gleam プログラムでは、gleam_erlang パッケージのgleam/erlang/referenceモジュールを利用するか、操作対象を絞ってもっと厳密な型を定義するのが一般的です(例: TransactionId や MessageTag など)。

外部を使って API を設計する

外部機能を利用する際、元の外部コードの API をそのまま模倣した Gleam の API を作りたくなるかもしれませんが、大抵の場合は悪手です。他言語で優れた API であっても、それが Gleam でも最適であるとは限らないからです。代わりに、通常の Gleam コードと同じように API を設計してください。Gleam の型システムなどの機能を活かし、不正な状態を表現できないような最良の API を目指しましょう。

たとえば、Erlang の zip モジュールには open 関数があります。これは ZIP アーカイブを受け取り、開かれたアーカイブへのハンドルを返します。このハンドルは、ファイルの中身を調べたり取り出したりする際に使用します。ハンドルの実態は Erlang の pid(プロセス識別子)であり、gleam_erlang パッケージは Pid というデータ型を定義しているため、API をそのまま再現するなら open 関数の戻り値にこれを使うことになるでしょう。しかしこの方法では、Gleam プログラムがその pid を「pid を期待する他のあらゆる関数」に渡せてしまいます。さらに、open 由来ではない pid を「ハンドルの pid を期待する zip モジュールの関数」に渡すことも可能です。どちらも不正な使い方ですが、型システムはこれらの間違いを防いでくれないため、開発者自身が実行時エラーを避けるよう注意深く実装しなければなりません。

より良い設計は、ハンドルの値専用の新しい外部型を作成し、その値だけが他の zip 関数に渡せるようにすることです。

// 悪い例
import gleam/erlang/process.{type Pid}

@external(erlang, "my_zip_library_ffi", "open")
pub fn open(zip: BitString) -> Result(Pid, ZipError)

@external(erlang, "my_zip_library_ffi", "extract_file")
pub fn extract(zip: Pid, file: String) -> Result(BitArray, ZipError)

// 良い例
pub type ZipHandle

@external(erlang, "my_zip_library_ffi", "open")
pub fn open(zip: BitString) -> Result(ZipHandle, ZipError)

@external(erlang, "my_zip_library_ffi", "extract_file")
pub fn extract(zip: ZipHandle, file: String) -> Result(ZipHandle, ZipError)

内部実装がどうであれ、API は常に Gleam の特性を念頭に置いて設計してください。

Erlang の外部

Erlang は、外部関数を宣言する対象としてもっとも素直な言語です。モジュール名と関数名は、Erlang コードでも Gleam の外部定義でもそのまま同じように記述します。どのモジュールのどの公開関数でも外部関数として利用できます。

-module(pokemon).
-export([badge_count/0]).

badge_count() ->
    8.

これは pokemon という名前の Erlang モジュールで、引数を取らない badge_count という公開関数を持っています。これに対応する Gleam 側の外部関数は次のようになります。

@external(erlang, "pokemon", "badge_count")
pub fn pokemon_badge_count() -> Int

Erlang のマクロは Erlang の外では使用できません。

Erlang での Gleam のデータ

Gleam のデータ型は Erlang でも一般的なデータ型にマッピングされるため、Erlang 側で Gleam のデータを扱うのは比較的簡単です。

以下に挙がっていない Erlang の型は、Gleam では外部型を使用して表現することになります。

Bool

Gleam の bool は Erlang のブーリアンのアトムになります。

// Gleam
True
False
% Erlang
true
false

Int

Gleam の int は Erlang の整数になります。

// Gleam
2001
% Erlang
2001

Float

Gleam の float は Erlang の浮動小数点数になります。

// Gleam
10.5
% Erlang
10.5

String

Gleam の文字列は Erlang の UTF-8 バイナリ文字列になります。

// Gleam
""
"Hello, Joe!"
"👷🏾‍♀️"
% Erlang
<<>>
<<"Hello, Joe!"/utf8>>
<<"👷🏾‍♀️"/utf8>>

Erlang の string() 型は文字を表す整数のリストであり、Gleam の文字列とは互換性がありません。Erlang の文字リストを Gleam の文字列へ変換するには、Erlang のunicode:characters_to_binary/1関数を使用してください。Erlang の文字リストを扱うには、gleam_erlang パッケージのgleam/erlang/charlistモジュールが役立つでしょう。

Nil

Gleam の Nil は Erlang のアトム nil になります。

// Gleam
Nil
% Erlang
nil

ビット配列

Gleam のビット配列は Erlang のビット列になります。

// Gleam
<<30, 56, 10>>
% Erlang
<<30, 56, 10>>

リスト

Gleam のリストは Erlang のリストになります。

// Gleam
[1, 2, 3]
% Erlang
[1, 2, 3]

Gleam では、リストのすべての要素が同じ型でなければなりません。

Gleam のリストは常に真リスト(proper list)です。Erlang の非真リストを Gleam コードへリストとして渡すのは誤りです。

タプル

Gleam のタプルは Erlang のタプルになります。

// Gleam
#(100, 1.9)
% Erlang
{100, 1.9}

Result

Gleam の result 型の Ok バリアントと Error バリアントは、Erlang のタグ付きタプルになります。

// Gleam
Ok(2)
Error(Nil)
% Erlang
{ok, 2}
{error, nil}

Erlang では、タグ付きタプルの代わりにアトムの ok や error だけを使うことがありますが、これらは Gleam の result 型とは互換性がありません。

カスタム型

Gleam のカスタム型のバリアントは、フィールドを持つかどうかに応じて、Erlang のタグ付きタプルまたはアトムになります。

Gleam の PascalCase のバリアント名は、Erlang では snake_case に変換されます。

// Gleam
Guest
User(id: 10)
SuperUser(id: 11)
guest
{user, 10}
{super_user, 11}

Gleam コンパイラは、カスタム型の定義ごとに Erlang のヘッダファイルを生成します。この中には各バリアントに対応する Erlang のレコード定義が含まれています。Erlang のレコードの構文を利用したい場合は、これらを Erlang モジュールへ include できます。

Dict

Gleam 標準ライブラリの dict は、Erlang のマップになります。

// Gleam
dict.new()
dict.from_list([#("a", 1), #("b", 2)])
% Erlang
#{}
#{<<"a"/utf8>> => 1, <<"b"/utf8>> => 2}

Gleam では、dict のすべてのキー同士、すべての値同士がそれぞれ同じ型でなければなりません。

Elixir の外部

Elixir の利用方法は Erlang の場合と似ています。

関数名は Elixir コードでもそのまま同じように記述します。Elixir ではモジュール名に暗黙の Elixir. という接頭辞が付くため、Elixir の外部関数を定義する際はこの接頭辞を指定する必要があります。どのモジュールのどの公開関数でも外部関数として利用できます。

defmodule Pokemon do
  def badge_count()
    8
  end
end

これは Pokemon という名前の Elixir モジュールで、引数を取らない badge_count という公開関数を持っています。これに対応する Gleam 側の外部関数は次のようになります。

@external(erlang, "Elixir.Pokemon", "badge_count")
pub fn pokemon_badge_count() -> Int

外部関数が Elixir で記述されていても、@external のターゲットは erlang のままである点に注意してください。これは Gleam コードが使用しているターゲットが Erlang だからです。

Elixir のマクロは Elixir の外では使用できません。

Elixir での Gleam のデータ

Gleam のデータ型は Elixir でも一般的なデータ型にマッピングされるため、Elixir 側で Gleam のデータを扱うのは比較的簡単です。

以下に挙がっていない Elixir の型は、Gleam では外部型を使用して表現することになります。

Bool

Gleam の bool は Elixir のブーリアンのアトムになります。

// Gleam
True
False
# Elixir
true
false

Int

Gleam の int は Elixir の整数になります。

// Gleam
2001
# Elixir
2001

Float

Gleam の float は Elixir の浮動小数点数になります。

// Gleam
10.5
# Elixir
10.5

String

Gleam の文字列は Elixir の文字列になります。

// Gleam
""
"Hello, Joe!"
"👷🏾‍♀️"
# Elixir
""
"Hello, Joe!"
"👷🏾‍♀️"

Nil

Gleam の Nil は Elixir のアトム nil になります。

// Gleam
Nil
# Elixir
nil

ビット配列

Gleam のビット配列は Elixir のビット列になります。

// Gleam
<<30, 56, 10>>
# Elixir
<<30, 56, 10>>

リスト

Gleam のリストは Elixir のリストになります。

// Gleam
[1, 2, 3]
# Elixir
[1, 2, 3]

Gleam では、リストのすべての要素が同じ型でなければなりません。

Gleam のリストは常に真リスト(proper list)です。Elixir の非真リストを Gleam コードへリストとして渡すのは誤りです。

タプル

Gleam のタプルは Elixir のタプルになります。

// Gleam
#(100, 1.9)
# Elixir
{100, 1.9}

Result

Gleam の result 型の Ok バリアントと Error バリアントは、Elixir のタグ付きタプルになります。

// Gleam
Ok(2)
Error(Nil)
# Elixir
{:ok, 2}
{:error, nil}

Elixir では、タグ付きタプルの代わりにアトムの ok や error だけを使うことがありますが、これらは Gleam の result 型とは互換性がありません。

カスタム型

Gleam のカスタム型のバリアントは、フィールドを持つかどうかに応じて、Elixir のタグ付きタプルまたはアトムになります。

Gleam の PascalCase のバリアント名は、Elixir では snake_case に変換されます。

// Gleam
Guest
User(id: 10)
SuperUser(id: 11)
:guest
{:user, 123}
{:super_user, 123}

Gleam コンパイラは、カスタム型の定義ごとに Erlang のヘッダファイルを生成します。この中には各バリアントに対応する Erlang のレコード定義が含まれています。Elixir のRecordモジュールが提供するマクロを利用したい場合は、これらを組み合わせて使用できます。

Dict

Gleam 標準ライブラリの dict は、Elixir のマップになります。

// Gleam
dict.new()
dict.from_list([#("a", 1), #("b", 2)])
# Elixir
%{}
%{"a" => 1, "b" => 2}

Gleam では、dict のすべてのキー同士、すべての値同士がそれぞれ同じ型でなければなりません。

JavaScript の外部

JavaScript の外部を定義する場合、モジュールは内部的に JavaScript の import 文で処理されるため、通常は JavaScript ファイルへのパスを指定する必要があります。パスは、その外部定義を含む Gleam ファイルの位置からの相対パスにします。関数名は JavaScript コードでの記述と同じになり、どのモジュールのどの公開関数でも外部関数として利用できます。

// src/my_app/pokemon.mjs 内
export function badge_count() {
  return 8;
}

これは src/my_app/pokemon.mjs にある JavaScript モジュールで、引数を取らない badge_count という公開関数を持っています。これに対応する、Gleam ファイル src/my_app.gleam 側の外部関数は次のようになります。

// src/my_app.gleam 内
@external(javascript, "./my_app/pokemon.mjs", "badge_count")
pub fn pokemon_badge_count() -> Int

JavaScript のランタイムはそれぞれ独自の ES モジュールの import 規則を持つため、使用中のランタイムにとってパスが正しいことを確認してください。たとえば Node.js では、import を機能させるために特別な .mjs という拡張子が必要になることがあります。先ほどの例でこの拡張子を使用しているのはそのためです。

node モジュールを使う

node モジュールは、JavaScript コードで使用するのと同じパスを指定すれば利用できます。たとえば、has-flag パッケージの hasFlag 関数を利用するには次のようにします。

@external(javascript, "has-flag", "hasFlag")
pub fn argv_has_flag(name: String) -> Bool

Gleam は npm などの JavaScript パッケージマネージャに対する特別なサポートを持たないため、利用するパッケージが存在するように JavaScript ランタイムを自分で構成する必要があります。Node.js を使用している場合は、package.json と npm install コマンドを利用してインストールすることになるでしょう。

自身のパッケージを Hex パッケージマネージャに公開する予定の場合、ベンダリング(依存コードを自分のプロジェクトにコピー&ペーストすること)は強く非推奨です。依存の重複排除ができなくなってコードが肥大化し、さらにセキュリティ監査やパッチ適用が極めて困難になるからです。代わりに、利用者がインストールすべき node モジュールを明確に文書化してください。

JavaScript から Gleam のモジュールを import する

Gleam の各モジュールは JavaScript の ES モジュールにコンパイルされるため、他の JavaScript コードから相対パスで import できます。パスは Gleam ファイルへのパスと同じですが、拡張子を .mjs に変更します。コンパイル後、プロジェクト内の各 Gleam パッケージは同じディレクトリに配置されるため、現在のパッケージのルートから上の階層へ移動し、目的の依存パッケージのディレクトリへ降りることで相対パスを記述できます。

src/code.mjs にあるファイルから、同じパッケージの visitor という Gleam モジュールを import するには次のようにします。

import * as visitor from "./visitor.mjs";

src/one/two/three.mjs にあるファイルから、同じパッケージの do/ray/me という Gleam モジュールを import するには次のようにします。

import * as me from "../../do/ray/me.mjs";

test/hello.mjs にあるファイルから、同じパッケージの world という Gleam モジュールを import するには次のようにします。

import * as world from "./world.mjs";

src/app/web.mjs にあるファイルから、wibble という名前のパッケージの one/two という Gleam モジュールを import するには次のようにします。

import * as two from "../../wibble/one/one.mjs";

JavaScript での Gleam のデータ

v1.13 以降、JavaScript へコンパイルされた Gleam コードは、Gleam のデータ型を構築するための API を公開します。

以下に挙がっていない JavaScript の型は、Gleam では外部型を使用して表現することになります。

Bool

Gleam の bool は JavaScript のブーリアンになります。

// Gleam
True
False
// JavaScript
true;
false;

Int

Gleam の int は JavaScript の数値になりますが、その数値は整数でなければなりません。

// Gleam
2001
// JavaScript
2001;

Float

Gleam の float は JavaScript の数値になり、こちらには何の制約もありません。

// Gleam
10.5
// JavaScript
10.5;

Gleam には無限大と NaN のための構文がないため、これらを Gleam コードに渡すのは避けるべきです。

String

Gleam の文字列は JavaScript の文字列になります。

// Gleam
""
"Hello, Joe!"
"👷🏾‍♀️"
// JavaScript
"";
"Hello, Joe!";
"👷🏾‍♀️";

Nil

Gleam の Nil は JavaScript の undefined になります。

// Gleam
Nil
// JavaScript
undefined

ビット配列

Gleam のビット配列は、Gleam の prelude モジュールの BitArray$BitArray 関数で構築します。この関数は Uint8Array を引数に取ります。

Gleam の prelude モジュールは、どの Gleam プロジェクトでも src/gleam.mjs に配置されているものとして import できます。このモジュールは Gleam のビルドツールが内部的に提供します。

// Gleam
<<30, 56, 10>>
// JavaScript、src/wibble/wobble.mjs 内
import { BitArray$BitArray } from '../gleam.mjs';

BitArray$BitArray(new Uint8Array([30, 56, 10]));

ビット配列を分解するために次の関数が提供されています。

  • BitArray$isBitArray: 値を受け取り、それがビット配列なら true を返します。
  • BitArray$data: ビット配列のデータを JavaScript の DataView として返します。ビット配列のビット数は 8 で割り切れなければならず、そうでなければ例外が発生します。

リスト

Gleam のリストは、Gleam の prelude モジュールの次の関数で構築します。

  • List$Empty: 引数を取らず、空のリストを返します。
  • List$NonEmpty: 要素と、リストの残りを引数に取ります。
// Gleam
[]
[1]
[1, 2, 3]
// JavaScript、src/wibble/wobble.mjs 内
import { List$Empty, List$NonEmpty } from '../gleam.mjs';

List$Empty();
List$NonEmpty(1, List$Empty());
List$NonEmpty(1, List$NonEmpty(3, List$NonEmpty(3, List$Empty()));

Gleam では、リストのすべての要素が同じ型でなければなりません。List$NonEmpty 関数の第 2 引数は、常に正しい型のリストである必要があります。

リストを分解するために次の関数が提供されています。

  • List$isEmpty: 値を受け取り、それが空のリストなら true を返します。
  • List$isNonEmpty: 値を受け取り、それが 1 つ以上の要素を持つリストなら true を返します。
  • List$NonEmpty$first: 空でないリストを受け取り、最初の要素を返します。
  • List$NonEmpty$rest: 空でないリストを受け取り、最初の要素を除いた残りのリストを返します。
// Gleam
case items {
  [] -> "Empty list"
  [e] -> "One element: " <> e
  [_, ..] -> "Multiple elements"
}
// JavaScript、src/wibble/wobble.mjs 内
import {
  List$isEmpty,
  List$NonEmpty$first,
  List$NonEmpty$rest,
} from '../gleam.mjs';

if (List$isEmpty(items)) {
  return "Empty list";
} else {
  const items2 = List$NonEmpty$rest(items)
  if (List$isEmpty(items2)) {
    const e = List$NonEmpty$first(items);
    return "One element: " + e;
  } else {
    return "Multiple elements";
  }
}

JavaScript で Gleam のリストを扱うのは、Gleam 内ほど快適ではありません。そのため、代わりに gleam_javascript パッケージのgleam/javascript/arrayモジュールの Array 型を利用し、Gleam コード内で配列をリストへ変換する、という選択肢もあります。

タプル

Gleam のタプルは JavaScript の配列になります。

// Gleam
#(100, 1.9)
// JavaScript
[100, 1.9];

Gleam のタプルはイミュータブルなので、Gleam のタプルとして使用されている配列を決して変更してはいけません。たとえば items.push(x) メソッドや items[i] = x といった代入構文は使用しないでください。

Result

Gleam の result は、Gleam の prelude モジュールの次の関数で構築します。

  • Result$Ok: 引数を 1 つ取り、Ok の値を返します。
  • Result$Error: 引数を 1 つ取り、Error の値を返します。
// Gleam
Ok(2)
Error("oh no!")
// JavaScript、src/wibble/wobble.mjs 内
import { Result$Ok, Result$Error } from '../gleam.mjs';

Result$Ok(2);
Result$Error("oh no!");

result を分解するために次の関数が提供されています。

  • Result$isOk: result を受け取り、それが Ok なら true を返します。
  • Result$isError: result を受け取り、それが Error なら true を返します。
  • Result$Ok$0: Ok の result を受け取り、内側の値を返します。
  • Result$Error$0: Error の result を受け取り、内側の値を返します。

Result$ 関連の関数へ渡す値は、すべて Gleam の result でなければなりません。Result$Ok$0 へ渡す値はすべて Ok の result、Result$Error$0 へ渡す値はすべて Error の result である必要があります。

カスタム型

Gleam で定義したカスタム型には、Gleam の result 型と同様の JavaScript 関数が生成されます。これらの関数は、そのカスタム型を定義している Gleam ファイルへのパスを指定して import できます。ただし、拡張子は .gleam ではなく .mjs にします。この場所に自分でファイルを作成してはいけません。ここは Gleam のビルドツールが内部的に提供します。

他のパッケージのモジュールを import する際は、そのパッケージの src ディレクトリが自分のプロジェクトのルートに配置されているものとしてパスを指定しますが、ディレクトリ名は src ではなくパッケージ名にします。たとえば、gleam_stdlib パッケージの gleam/option モジュールを利用したく、それを import する JavaScript ファイルが src/wibble/wobble.js にある場合、import のパスは ../../gleam_stdlib/gleam/option.mjs になります。

カスタム型向けに提供される JavaScript の API を説明するために、次の SchoolPerson というカスタム型を使います。

// Gleam、src/school.gleam 内
pub type SchoolPerson {
  Teacher(name: String)
  Student(name: String, year: Int)
}

カスタム型のバリアントごとに、そのバリアントを構築するための TypeName$VariantName 関数が提供されます。これらは、Gleam コードでバリアントのコンストラクタが取るのと同じ引数を取ります。

// Gleam
Teacher("Mr Schofield")
Student("Adam", 7)
// JavaScript、src/code.mjs 内
import { SchoolPerson$Teacher, SchoolPerson$Student } from './school.mjs';

SchoolPerson$Teacher("Mr Schofield");
SchoolPerson$Student("Adam", 7);

カスタム型のバリアントごとに、値がどのバリアントかを判定するための TypeName$isVariantName 関数が提供されます。この関数へ渡す値は正しい型である必要があります。

// JavaScript、src/code.mjs 内
import {
  SchoolPerson$Teacher,
  SchoolPerson$isTeacher,
  SchoolPerson$isStudent,
} from '../school.mjs';

const teacher = SchoolPerson$Teacher("Mr Schofield")

SchoolPerson$isTeacher(teacher);
// -> true

SchoolPerson$isStudent(teacher);
// -> false

カスタム型の各バリアントのフィールドごとに、そのフィールドを位置で参照するための TypeName$VariantName$index 関数が提供されます。これらの関数へ渡す値は、正しいバリアントである必要があります。

// JavaScript、src/code.mjs 内
import {
  SchoolPerson$Student,
  SchoolPerson$Student$0,
  SchoolPerson$Student$1,
} from '../school.mjs';

const student = SchoolPerson$Student("Koushiar", 7);

SchoolPerson$Student$0(student);
// -> "Koushiar"

SchoolPerson$Student$1(student);
// -> 7

フィールドにラベルが付けられている場合は、フィールドの位置ではなくラベル名を使った同様の関数も提供されます。これらの関数へ渡す値は、正しいバリアントである必要があります。

// JavaScript、src/code.mjs 内
import {
  SchoolPerson$Student,
  SchoolPerson$Student$name,
  SchoolPerson$Student$year,
} from '../school.mjs';

const student = SchoolPerson$Student("Koushiar", 7);

SchoolPerson$Student$name(student);
// -> "Koushiar"

SchoolPerson$Student$year(student);
// -> 7

すべてのバリアントを通じて、同じ位置のフィールドが同じラベルを持つ場合は、それらを参照するための TypeName$label_name 関数が提供されます。これらの関数へ渡す値は正しい型である必要がありますが、どのバリアントでも構いません。

// JavaScript、src/code.mjs 内
import {
  SchoolPerson$Student,
  SchoolPerson$Teacher,
  SchoolPerson$name,
} from '../school.mjs';

const teacher = SchoolPerson$Teacher("Mr Schofield");
const student = SchoolPerson$Student("Koushiar", 7);

SchoolPerson$name(teacher);
// -> "Mr Schofield"

SchoolPerson$name(student);
// -> "Koushiar"

Dict

dict 型のように Gleam でリテラル構文を持たない型には、特別な JavaScript の API がありません。こうした型については、通常の Gleam の関数を import して利用できます。

// Gleam
dict.from_list([
  #("Lucy", 2),
  #("Ada", 1),
])
// JavaScript、src/code.mjs 内
import { from_list as list_to_dict }
  from '../gleam_stdlib/gleam/dict.mjs';
import { to_list as array_to_list }
  from '../gleam_stdlib/gleam/javascript/array.mjs';

list_to_dict(array_to_list([
  ["Lucy", 2],
  ["Ada", 1],
]));

原文: Externals guide(https://gleam.run/documentation/externals/)

原文の commit: d5d2c91fcc65aa4e9fa2ac70a9ab397c53a1c92d(pages/documentation/externals.djot)

ライセンス: Apache-2.0。訳: 水無瀬[PL]、2026-09-16。

© 2026 Canonicalgleam.canon-ical.com