← スキル一覧に戻る
Barrel File Pattern (

creating-adts
by jasonkuhrt
Tool configurations
⭐ 1🍴 0📅 2026年1月22日
SKILL.md
name: creating-adts description: This skill should be used when the user asks to "create an ADT", "scaffold a discriminated union", "add a tagged union", "create Effect Schema union", or needs to create algebraic data types following the ADT library pattern with proper member files and barrel exports.
Creating ADTs
Scaffold ADT (Algebraic Data Type) unions with discriminated member types.
CRITICAL
Read the Conventions First
Before creating any ADT, read the convention documents:
~/.claude/docs/conventions/namespace-module.md— Core_.ts/__.tspattern~/.claude/docs/conventions/library-adt.md— ADT-specific patterns
Operations
Create ADT Union
Structure:
src/lib/<adt-name>/
├── _.ts # export * as AdtName from './__.js'
├── __.ts # exports member namespaces + union
├── <adt-name>.ts # Union definition
├── <member-a>.ts # Member type
└── <member-b>.ts # Member type
Steps:
- Create directory at
src/lib/<adt-name>/(kebab-case matching ADT name) - Create member files with tagged structs
- Create union file importing members directly (NOT from
__.ts) - Create
__.tsexporting members as namespaces + union exports - Create
_.tspointing to__.ts - Add package.json imports and tsconfig.json paths
Member File Pattern (Effect Schema)
// <member>.ts
import * as S from 'effect/Schema'
export class MemberName extends S.TaggedClass<MemberName>()('AdtNameMemberName', {
// fields...
}) {
static is = S.is(MemberName)
}
Naming Rules:
- Class name = member name (short, local):
Versioned - Tag name = fully qualified:
DocumentVersioned
Union File Pattern
// <adt-name>.ts
import * as S from 'effect/Schema'
import { MemberA } from './member-a.js' // Direct import, NOT from __.ts
import { MemberB } from './member-b.js'
export const AdtName = S.Union(MemberA, MemberB)
export type AdtName = typeof AdtName.Type
Barrel File Pattern (__.ts)
// __.ts
export * from './<adt-name>.js'
export * as MemberA from './member-a.js'
export * as MemberB from './member-b.js'
Examples
LifecycleEvent ADT
// added.ts
export class Added extends S.TaggedClass<Added>()('LifecycleEventAdded', {
schema: SchemaRef,
revision: Revision,
}) {
static is = S.is(Added)
}
// removed.ts
export class Removed extends S.TaggedClass<Removed>()('LifecycleEventRemoved', {
schema: SchemaRef,
revision: Revision,
}) {
static is = S.is(Removed)
}
// lifecycle-event.ts
import { Added } from './added.js'
import { Removed } from './removed.js'
export const LifecycleEvent = S.Union(Added, Removed)
export type LifecycleEvent = typeof LifecycleEvent.Type
// __.ts
export * as Added from './added.js'
export * from './lifecycle-event.js'
export * as Removed from './removed.js'
// _.ts
export * as LifecycleEvent from './__.js'
Consumer Usage
// Import ONLY from namespace (_.js)
import { LifecycleEvent } from '#lifecycle-event'
// Access members via namespace
const added = LifecycleEvent.Added.make({ schema, revision })
const removed = LifecycleEvent.Removed.make({ schema, revision })
// Type check
if (LifecycleEvent.Added.is(event)) {
// event is Added
}
Notes
- Union file imports members directly to avoid circular dependencies
- Consumer code imports ONLY from
_.js, never from__.js - Use
.make()constructor from tagged classes, never manual object construction - Tag names should be fully qualified (
AdtNameMemberName) for global uniqueness - See convention doc for Simple ADT Pattern (alternative when full structure is overkill)
スコア
総合スコア
55/100
リポジトリの品質指標に基づく評価
✓SKILL.md
SKILL.mdファイルが含まれている
+20
○LICENSE
ライセンスが設定されている
0/10
○説明文
100文字以上の説明がある
0/10
○人気
GitHub Stars 100以上
0/15
✓最近の活動
1ヶ月以内に更新
+10
○フォーク
10回以上フォークされている
0/5
✓Issue管理
オープンIssueが50未満
+5
✓言語
プログラミング言語が設定されている
+5
✓タグ
1つ以上のタグが設定されている
+5
レビュー
💬
レビュー機能は近日公開予定です



