Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
TSX の <Hoge<Fuga>> という構文に驚いた話 / tsx-type-argume...
Search
Kanaru
July 27, 2026
Programming
240
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
TSX の <Hoge<Fuga>> という構文に驚いた話 / tsx-type-argument-syntax
Kanaru
July 27, 2026
More Decks by Kanaru
See All by Kanaru
自宅鯖のための IaC / クラウド活用
kanaru0928
0
36
Other Decks in Programming
See All in Programming
AWS DevOps AgentのAzure接続機能を検証して見えた活用法/Use Cases Verified for the AWS DevOps Agent's Azure Connectivity Feature
masakiokuda
1
270
typoなんかねぇよ
raspython3
0
560
AIの中の人になってみる
htkym
0
130
Jindong: Introducing Declarative Haptics in Compose Multiplatform
l2hyunwoo
0
130
VibeCodingからAgenticWorkflowへ
starfish719
0
890
Press start. Python's next generation.
willingc
PRO
3
190
[PyCon KR 2026] More Variants, More Diversity for AI Accelerators
achimnol
0
110
複数の Claude Code が"放置"されてしまう問題をCLI ダッシュボードを自作して解決した話
sumihiro3
1
730
【デモ】Kiroで体験する仕様駆動開発|設計からコーディングまでAIと進める開発フロー
cmkudo
0
410
片田舎のおっさん、 Swift Buildのダイアモンド問題解決の不具合修正PRを出すが、解決方法がキャッシュをしないようにすることであり、ビルド時間が伸びると言われてマージされないので高速化もする/swiftbuild
yimajo
0
290
私のClaude Code活用法 (個人開発編) - PHPerKaigi mini #4(2026/08/24)
panda_program
1
170
in-process GraphQL のすすめ #ginzajs
izumin5210
4
1.5k
Featured
See All Featured
Taking LLMs out of the black box: A practical guide to human-in-the-loop distillation
inesmontani
PRO
3
2.4k
The State of eCommerce SEO: How to Win in Today's Products SERPs - #SEOweek
aleyda
2
11k
The Cult of Friendly URLs
andyhume
79
7k
Visual Storytelling: How to be a Superhuman Communicator
reverentgeek
2
620
How Fast Is Fast Enough? [PerfNow 2025]
tammyeverts
3
820
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
508
140k
Claude Code どこまでも/ Claude Code Everywhere
nwiizo
67
57k
Navigating Algorithm Shifts & AI Overviews - #SMXNext
aleyda
1
1.6k
コードの90%をAIが書く世界で何が待っているのか / What awaits us in a world where 90% of the code is written by AI
rkaga
63
45k
Noah Learner - AI + Me: how we built a GSC Bulk Export data pipeline
techseoconnect
PRO
0
400
Rails Girls Zürich Keynote
gr2m
96
14k
YesSQL, Process and Tooling at Scale
rocio
174
15k
Transcript
TSX の <Hoge<Fuga>> という 構文に驚いた話 Kanaru 雑LT_study 2026-07-27
自己紹介 Kanaru @kanaru0928 • 普段は学生 • インフラとかバックエンドとか • 趣味 7
割、業務 3 割 興味 クラウド / アーキテクチャ 言語 Go / TypeScript / Python 2
背景 3
背景 AI にフロントを書かせてたら出てきた • React + TypeScript + Cloudscape(UI ライブラリ)
home.tsx !? <Cards<AnsweredEvent> header={<Header variant="h2">Events</Header>} items={answeredEvents} trackBy={(event) => event.eventId} ... /> 4
答え合わせ TypeScript のリリースノート • 型引数を表している • TS 2.9 でこの構文が追加 引用
https://www.typescriptlang.org/docs/handbook/release-notes/ typescript-2-9.html#generic-type-arguments-in-jsx-elements 5
なぜ違和感を覚えたのか 6
予想 そもそも要素名には何を入れられるか • 要素名 <Hoge fuga={piyo} /> の Hoge の部分
• <Hoge /> 一番見る形 • <Hoge<Fuga> /> さっき見た(Cloudscape など) • <Hoge.Fuga /> たまに見る(RadixUI など) 7
予想 そもそも要素名には何を入れられるか • 式ならなんでも入りそう? • <Hoge[0] /> ワンチャンいける? • <Hoge()
/> うーん怪しい • <Hoge as Fuga /> これはダメそう • 境界が謎 8
JSX の仕様書 JSX では要素名に約物(かっこなど)が入ってはいけない • 参考 https://react.github.io/jsx/#sec-jsx-elements JSX Specification OpeningElement
::= “<” ElementName [Attributes] “>” ElementName ::= Identifier | NamespacedName | MemberExpression Identifier ::= 文字列 (“<“ や “>” などの約物は除く) NamespcedName ::= Identifier “:” Identifier MemberExpression ::= Identifier “.” Identifier | MemberExpression “.” Identifier 9
TypeScript に仕様書は存在しない Microsoft「† 実装が仕様 †」 10
パーサを見る JSX は <要素名 属性 /> だけど… parser.go func (p
*Parser) parseJsxOpeningOrSelfClosingElementOrOpeningFragment (inExpressionContext bool) *ast.Expression { ... tagName := p.parseJsxElementName() var typeArguments *ast.NodeList if p.contextFlags&ast.NodeFlagsJavaScriptFile == 0 { typeArguments = p.parseTypeArguments() } attributes := p.parseJsxAttributes() ... return p.finishNode(result, pos) } 引用 https://github.com/microsoft/typescript-go/blob/typescript/v7.0.2/internal/parser/parser.go#L4933-L4966 11
パーサを見る 特別に入れられた構文 parser.go func (p *Parser) parseJsxOpeningOrSelfClosingElementOrOpeningFragment (inExpressionContext bool) *ast.Expression
{ ... tagName := p.parseJsxElementName() var typeArguments *ast.NodeList 謎の構文規則が if p.contextFlags&ast.NodeFlagsJavaScriptFile == 0 { typeArguments = p.parseTypeArguments() 足されている!! } attributes := p.parseJsxAttributes() ... return p.finishNode(result, pos) } 引用 https://github.com/microsoft/typescript-go/blob/typescript/v7.0.2/internal/parser/parser.go#L4933-L4966 12
パーサを見る 分かったこと • 要素名は「項」や「式」などの単位ではなく専用の構文が存在する • 識別子(Hoge) • メンバー式(Hoge.Fuga.Piyo) • 名前空間付き識別子(Hoge:Fuga)
• (TS 限定)型引数が付与可能(Hoge<Fuga>) • 型引数が特別扱いなので違和感があった 13
結論 積極的に使うことはなさそう • ほとんどのケースで型推論が効く • 可読性が悪い • そんな複雑なコンポーネントを作る機会がない explicit.tsx <Cards<AnsweredEvent>
items={answeredEvents} ... /> 型推論により 省略可能 implicit.tsx <Cards items={answeredEvents} ... /> 14