Custom Elements ManifestのJSX型定義から名前のないイベントを除外
StencilJSとの互換性を高めるため、Custom Elements Manifest(CEM)の解析プロセスから名前のないイベントエントリを除外する仕組みが追加されました。これにより、JSX型定義に onundefined のような不正なイベントハンドラが生成される問題が解消されます。
背景
CEMアナライザーは2つの方法でイベントを検出していました。1つは @event JSDocタグからの検出(イベント名を含む)、もう1つはコード内の dispatchEvent() 呼び出しの解析(型のみで名前を含まない)です。この二重検出により、一部のイベントエントリに名前が欠落し、JSX型生成時に onundefined のような不正なイベントハンドラが生成されていました。
#1919 で報告されたこの問題は、StencilプロジェクトでWeb Awesomeを使用する際に型エラーを引き起こしていました。<wa-button onClick={...} /> のような有効なStencil TSXコードが、Property 'onClick' does not exist というエラーで失敗する状況でした。
問題の根本原因は、dispatchEvent() 呼び出しから検出されたイベントが name プロパティを持たず、JSX型生成器がこれを onundefined として出力していたことです。wa-icon、wa-button、wa-input、wa-select、wa-dialog、wa-drawer、wa-dropdown、wa-tooltip を含む25個のコンポーネントでこの問題が発生していました。
技術的な変更
custom-elements-manifest.js に wa-filter-unnamed-events プラグインが追加され、JSX型生成前に名前のないイベントを除外するようになりました。
変更内容:
// Filter out events without names (these come from code analysis detecting
// dispatchEvent() calls, but lack the event name that comes from @event JSDoc tags)
{
name: 'wa-filter-unnamed-events',
packageLinkPhase({ customElementsManifest }) {
customElementsManifest?.modules?.forEach(mod => {
mod.declarations?.forEach(dec => {
if (dec.kind === 'class' && dec.events) {
dec.events = dec.events.filter(event => event.name);
}
});
});
},
},
このプラグインは packageLinkPhase で動作し、CEM内の各クラス宣言の events 配列から name プロパティを持たないエントリをフィルタリングします。
JSX型生成の設定にも変更が加えられました:
jsxTypesPlugin({
fileName: 'custom-elements-jsx.d.ts',
outdir,
defaultExport: true,
includeDefaultDOMEvents: true, // 追加
componentTypePath: (_name, _tag, modulePath) => {
return `./${modulePath}`;
},
}),
includeDefaultDOMEvents: true が追加され、onClick のような標準DOMイベントがJSX型定義に含まれるようになりました。これにより、StencilプロジェクトでWeb Awesomeコンポーネントに標準イベントハンドラをバインドできるようになります。
設計判断
イベント検出の仕組み自体を変更するのではなく、型生成前のフィルタリング というアプローチが採用されました。
コード解析による dispatchEvent() の検出は、開発者が @event タグを付け忘れた場合のフォールバックとして有用です。しかし、この検出方法では呼び出し箇所から型情報しか取得できず、イベント名は得られません。両方の検出方法を維持しつつ、名前のないエントリだけを除外することで、@event タグで明示的に宣言されたイベントと、タグがあってコードにも実装があるイベントの両方を適切に処理できます。
PR内の議論では、ビルドプロセスに検証ステップを追加することも提案されました。CEMに名前のないイベントが残っていないか、生成されたJSX型に onundefined が含まれていないかをチェックし、検出された場合はビルドを失敗させます。この検証により、問題の再発を防ぐ仕組みが整いました。
まとめ
本PRは、Custom Elements Manifestの解析プロセスにフィルタリング段階を追加することで、StencilJSとの型互換性を確立しました。名前のないイベントエントリを除外し、標準DOMイベントのサポートを明示的に有効化することで、25個のコンポーネントにわたる型定義の問題が解消され、StencilプロジェクトでWeb Awesomeを使用する際の開発体験が向上します。