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
210
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
25
Other Decks in Programming
See All in Programming
S3 を使うアプリケーションをローカル完結で動かすことに全力を注いでみた / Running S3 Apps Offline
contour_gara
0
130
仕様駆動開発の消費期限
watany
11
4.9k
プロポーザルを書いてもらう
pvcresin
0
220
the container ship “Apple Silicon”@WWDC26 Recap -Japan-\(region).swift
shingangan
0
100
Claude CodeとAgentCore Gatewayを繋ぐ際の認証認可 / Authentication and authorization when connecting Claude Code with AgentCore Gateway
har1101
1
230
VibeCodingからAgenticWorkflowへ
starfish719
0
250
AI Engineeringは、AIプロダクトだけのものか? 〜AIがソフトウェアを作る時代の新しい当たり前〜 / No AI in your product. AI Engineering in your development.
rkaga
4
370
React本体のコードリーディング
high_g_engineer
1
130
Go言語とトイモデルで学ぶTransformerの気持ち / fukuokago23-transformer
monochromegane
0
160
Android CLI
fornewid
0
210
そこに3びきプロダクトがいるじゃろう——生成AI時代における“価値が届かない理由”の構造
kosuket
0
410
Google Apps Script で Ruby を動かす
kawahara
0
130
Featured
See All Featured
Utilizing Notion as your number one productivity tool
mfonobong
4
510
Lightning talk: Run Django tests with GitHub Actions
sabderemane
0
230
Agile Leadership in an Agile Organization
kimpetersen
PRO
0
200
Chrome DevTools: State of the Union 2024 - Debugging React & Beyond
addyosmani
10
1.3k
The Straight Up "How To Draw Better" Workshop
denniskardys
239
140k
DevOps and Value Stream Thinking: Enabling flow, efficiency and business value
helenjbeal
1
290
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
37
6.5k
Marketing to machines
jonoalderson
1
5.6k
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
234
17k
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
46
2.9k
Navigating the moral maze — ethical principles for Al-driven product design
skipperchong
2
450
コードの90%をAIが書く世界で何が待っているのか / What awaits us in a world where 90% of the code is written by AI
rkaga
63
45k
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