開発者ガイド
Jev TypeSafe:TypeScriptに型付きAI判断を組み込む
Jev TypeSafeの実践ガイド。型付き質問を定義し、API応答を実行時に検証して、TypeScriptアプリで不確実な判断を安全に振り分けます。

jev typesafeで検索すると、関連はあるものの異なる二つの概念に行き着くことがあります。Jevの型付きAI判断と、TypeScriptの型システムです。このガイドでは、コンパイル時の型を信頼できる実行時データと混同せずに、両者を連携する方法を解説します。Jevは状態に関する構造化された質問に回答しますが、その応答を検証し、アプリが何を実行できるかを決めるのはTypeScriptサービスです。
Jevのサイトでは、ソフトウェアチーム向けの独立した判断ツールとして紹介されています。JevはTypeSafeと提携・運営関係になく、TypeSafeからの推奨も受けていません。まずはJev AIのホームページとオンラインPlaygroundをご覧ください。

TypeScriptアプリで「Jevを型安全に使う」とは
TypeScriptは実行前にコードを検査します。しかし、リモートサービスのHTTP応答が宣言した型に一致することまでは証明できません。response.json()の値は、構造を確認するまでunknownとして扱います。
重要な境界は二つあります。
- リクエストの構築: TypeScriptで状態や質問の定義を一貫させます。
- 応答の解析: 実行時検査で、ネットワークデータに必要なフィールドがあることを確認します。
モデルの回答は判断のシグナルであり、操作の実行許可ではありません。実行を制御するのは、アプリ独自の業務ルール、決定的な検査、承認フローです。

Jevの三つの質問タイプから始める
Jevのドキュメントでは、三つの型付き質問が説明されています。固定の振り分け先にはChoice、順序のある評価にはScore、明確なYes/No判断にはNoulを使います。一つの状態に対して、複数の質問を同じリクエストで行えます。
| タイプ | 適した用途 | 確認する結果 |
|---|---|---|
| Choice | チーム、キュー、カテゴリの選択 | 選択肢、各確率、confidence |
| Score | 順序尺度による重大度、品質、緊急度 | 加重スコア、段階ごとの確率、confidence |
| Noul | 明確な命題が真かどうか | 「はい」である確率(0〜1) |
判定基準は具体的に記述します。チケットを請求、技術、営業に分けるなら、Jevに分類を作らせず、各選択肢に当てはまる条件を示しましょう。

型付きリクエストを作り、応答を検証する
以下は、サーバー側のTypeScriptサービスから、ドキュメントにあるSystem Oneエンドポイントを呼び出す例です。リクエストの形を型で表し、APIキーをサーバー内に置き、unknownとして受け取ったJSONの構造を確認してからアプリに返します。
type Question =
| { type: "choice"; instructions: string; criteria: Record<string, string> }
| { type: "score"; instructions: string; criteria: string[] }
| { type: "noul"; instructions: string };
type EvaluationRequest = {
model: "jev-latest";
state: string | Record<string, unknown> | string[];
questions: Record<string, Question>;
};
function asRecord(value: unknown): Record<string, unknown> | null {
return typeof value === "object" && value !== null && !Array.isArray(value)
? (value as Record<string, unknown>)
: null;
}
function isProbabilityMap(value: unknown): value is Record<string, number> {
const map = asRecord(value);
return !!map && Object.values(map).every(
(item) => typeof item === "number" && Number.isFinite(item) && item >= 0 && item <= 1
);
}
async function classifyTicket(ticket: string) {
const apiKey = process.env.JEV_API_KEY;
if (!apiKey) throw new Error("JEV_API_KEY is not configured");
const request = {
model: "jev-latest",
state: { message: ticket },
questions: {
department: {
type: "choice",
instructions: "Which team should handle this ticket?",
criteria: {
billing: "Payments, invoices, refunds, or payouts",
technical: "Bugs, outages, or integration failures",
sales: "Pricing, upgrades, or new accounts"
}
}
}
} satisfies EvaluationRequest;
const response = await fetch("/ja/v1/systemone", {
method: "POST",
headers: {
Authorization: "Bearer " + apiKey,
"Content-Type": "application/json"
},
body: JSON.stringify(request)
});
if (!response.ok) throw new Error("Jev request failed: " + response.status);
const payload: unknown = await response.json();
const root = asRecord(payload);
const answers = asRecord(root?.answers);
const answer = asRecord(answers?.department);
if (
answer?.type !== "choice" ||
typeof answer.choice !== "string" ||
typeof answer.confidence !== "number" ||
!Number.isFinite(answer.confidence) ||
answer.confidence < 0 ||
answer.confidence > 1 ||
!isProbabilityMap(answer.probabilities)
) {
throw new Error("Unexpected Jev response shape");
}
return {
team: answer.choice,
confidence: answer.confidence,
probabilities: answer.probabilities
};
}
const result = await classifyTicket("Three deploys failed and production is returning 500s.");
if (result.confidence >= 0.8) {
// Apply your allowlist and business rules before routing.
} else {
// Send uncertain cases to a human-review queue.
}
この検証は、このワークフローが使うフィールドを確認します。後続処理が別のフィールドを使うなら、その項目も検証してください。応答全体を宣言済みの型へキャストしただけで、リモートサービスがその型を満たすと考えてはいけません。

confidenceは保証ではなくシグナルとして使う
JevのChoiceとScore応答には各選択肢の確率とconfidenceが含まれ、Noulは「はい」の確率を返します。これらは比較や振り分けに役立ちますが、confidenceは測定済みの正確さと同じではなく、安全性の保証でもありません。
自動化する前に、実際の用途を代表するラベル付きサンプルを用意します。重要な誤りを測定し、その結果に基づいてしきい値を設定し、未満の場合の処理を決めます。影響の大きい操作では、モデルのシグナルが強くても、決定的なポリシー検査と人の承認を残してください。

Jev TypeSafeを本番導入する際の確認事項
- 判断に必要なテキストや構造化フィールドだけを送り、無関係な個人情報は除きます。
- JEV_API_KEYはサーバー側のシークレットストアに保存します。ブラウザーコードや公開リポジトリには置きません。
- 実操作へ接続する前に、Jev Playgroundで通常例、曖昧な例、敵対的な例を試します。
- リクエストIDと検証結果を記録し、認証情報や不要な機密状態はログに残しません。
- 一時的なHTTP 429・529には、上限付きの指数バックオフを使用します。
- スキーマ不一致はエラーとして扱い、黙って既定の操作を選ばないようにします。
- 入力の傾向や業務コストが変わったら、しきい値を見直します。
現在のリクエストと応答のフィールドはJev APIドキュメントを確認してください。本番利用量を見積もる際はプランと使用量も参照できます。
Jev TypeSafeはTypeScriptと同じですか?
違います。Jevは選択、スコア、Yes確率などの型付き判断結果を返します。TypeScriptはアプリのコードを静的に検査します。堅牢な連携には両方が必要です。リクエストと内部結果に型を付け、信頼できないネットワークデータは実行時に検証します。
TypeScriptの型でAPI応答を検証できますか?
できません。型注釈はJavaScriptの実行前に消えます。応答をunknownとして解析し、振り分け、保存、表示の前に、アプリが依存するフィールドを検査してください。
判断後にJevが操作を実行しますか?
実行はアプリ側で管理します。Jevには範囲の定まった質問を評価させ、アプリ独自の権限、許可リスト、決定的ルール、承認手順で続行を判断します。
まとめ
実用的なjev typesafe連携では、モデルの構造化判断と、それを使うアプリのロジックとの境界を明確にします。質問を絞り、応答を実行時に検証し、実例で評価し、不確実または影響の大きいケースは確認フローへ送ります。