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
プロダクト開発とTypeScript
Search
Taketoshi Aono(青野健利 a.k.a brn)
October 02, 2019
Programming
8
2.9k
プロダクト開発とTypeScript
TypeScriptによるプロダクト開発の知見
Taketoshi Aono(青野健利 a.k.a brn)
October 02, 2019
Tweet
Share
More Decks by Taketoshi Aono(青野健利 a.k.a brn)
See All by Taketoshi Aono(青野健利 a.k.a brn)
document.write再考
brn
6
3k
Parsing Javascript
brn
14
9.3k
JSON & Object Tips
brn
1
500
CA 1Day Youth Bootcamp for Frontend LT
brn
0
960
Modern TypeScript
brn
2
810
javascript - behind the scene
brn
3
740
tc39 proposals
brn
0
880
React-Springでリッチなアニメーション
brn
1
700
javascript internationalization API
brn
0
890
Other Decks in Programming
See All in Programming
PHPカンファレンス関西2025 基調講演
sugimotokei
6
1.1k
変化を楽しむエンジニアリング ~ いままでとこれから ~
murajun1978
0
670
実践!App Intents対応
yuukiw00w
1
210
AIに安心して任せるためにTypeScriptで一意な型を作ろう
arfes0e2b3c
0
330
令和最新版手のひらコンピュータ
koba789
13
5.9k
Strands Agents で実現する名刺解析アーキテクチャ
omiya0555
1
110
Gemini CLIの"強み"を知る! Gemini CLIとClaude Codeを比較してみた!
kotahisafuru
3
930
MySQL9でベクトルカラム登場!PHP×AWSでのAI/類似検索はこう変わる
suguruooki
1
280
DynamoDBは怖くない!〜テーブル設計の勘所とテスト戦略〜
hyamazaki
0
190
画像コンペでのベースラインモデルの育て方
tattaka
3
1.3k
PHPUnitの限界をPlaywrightで補完するテストアプローチ
yuzneri
0
380
Vibe coding コードレビュー
kinopeee
0
420
Featured
See All Featured
Building Flexible Design Systems
yeseniaperezcruz
328
39k
Visualization
eitanlees
146
16k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
248
1.3M
Designing Dashboards & Data Visualisations in Web Apps
destraynor
231
53k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
33
2.4k
StorybookのUI Testing Handbookを読んだ
zakiyama
30
6k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
50
5.5k
Faster Mobile Websites
deanohume
308
31k
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
15
1.6k
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
34
3.1k
Fantastic passwords and where to find them - at NoRuKo
philnash
51
3.4k
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
PRO
183
54k
Transcript
Product development with TypeScript
Name !CSO 5BLFUPTIJ"POP੨݈ར Occupation 'SPOUFOE%FWFMPQFS1SPEVDU0XOFS Company $ZCFSBHFOU"EUFDI4UVEJP"*.FTTFOHFS OSS $POUSJCVUPSPG7
About IUUQJOGPCODI
1SPEVDUEFWFMPQFEFGGFDUJWFMZ 5ZQF4DSJQUಋೖͯ͠ϓϩμΫτ։ൃͷੜ࢈ੑ্͕Γ·͔ͨ͠ʁ ಋೖ͚ͨͩ͠Ͱͳ͔ͳ͔͍͔͠͠Ε·ͤΜɻ ࠓͷτʔΫ͕ ੜ࢈ੑΛͰ͖Δ্͚ͩ͛ΔͨΊͷΨΠυͱͳΔ͜ͱΛئ͍·͢ɻ
*NQPSUBOUUIJOHTBCPVU5ZQF4DSJQU 5ZQF4DSJQUͷॏཁͳͰ͢ KBWBTDSJQUͰͳ͍͕KBWBTDSJQUͰ͋Δ ܕ࣮ߦ࣌ʹফ͑Δ
ػೳ
#FGPSFBMM લఏͱͯ͠UTDPOpHKTPOͰҎԼͷػೳඞͣ0/ʹ͠·͠ΐ͏ OP*NQMJDJU"OZ TUSJDU
*NQPSUBOUUIJOHTBCPVU5ZQF4DSJQU KBWBTDSJQUͰͳ͍͕KBWBTDSJQUͰ͋Δ 5ZQF4DSJQUKBWBTDSJQUͷ4VQFS4FUΛᨳ͍ͬͯ·͢ ͦͷͨΊ༷తʹ+BWBTDSJQUΛ౿ऻ͍ͯ͠·͕͢ ͋͘·Ͱผͷݴޠͱଊ͑ͨ΄͏͕ྑ͍Ͱ͢ ͦͷ্Ͱ͍͔ͭ͘ॏཁͳʹ͍͓ͭͯ͠·͢
FOVN FOVN5ZQF4DSJQUͷಠࣗػೳͰ͢ KBWBTDSJQUʹແ͍ͱ͍͏ҙຯࠓޙಉ ͡ҙຯͰ͍·͢
enum Card { SPADE, HEART, DIAMOND, CLUB } // ࿈൪
assert.equal(Card.SPADE, 0); assert.equal(Card.DIAMOND, 2); // ٯҾ͖ assert.equal(Card[Card.DIAMOND], 'DIAMOND');
enum Event { CLICK = 'CLICK', MOUSEOVER = 'MOUSEOVER'; }
FOVN FOVN͜ͷΑ͏ʹΛ·ͱΊΔͷʹར༻͠·͕͢ FOVN͕ࣗܕΛߏ͠ɺܕνΣοΫʹར༻Ͱ͖·͢ ͨͩ͠ҙ͕͋Γ·͢
enum Card { SPADE, HEART, DIAMOND, CLUB } const fn
= (card: Card) => { return card; } fn(Card.SPADE); // OK fn(0); // OK fn(10); // OK
FOVN FOVNΛͦͷ··ར༻͢Δͱɺ୯७ͳOVNCFSܕͱͳΓͷൣғΛνΣο Ϋͯ͘͠Ε·ͤΜ ͦͷͨΊෆਖ਼ͳΛ͢͜ͱՄೳʹͳΓ·͢
enum EventType { CLICK = 'CLICK', MOUSEOVER = 'MOUSEOVER'; }
const fn2 = (event: EventType) => {return event;} fn2(EventType.CLICK); fn2(EventType.MOUSEOVER); fn2("MOUSEDOWN"); // NG
FOVN จࣈྻΛͬͨ߹ʹਖ਼͘͠FOVNʹఆٛ͞Ε͍ͯΔͷνΣοΫΛߦ ͍·͢ ·ͨΛܕͱͯ͠͏͜ͱͰ5BHHFE6OJPOͱͯ͠͏͜ͱ͕Ͱ͖·͢
enum EventType { CLICK = 'CLICK', MOUSEOVER = 'MOUSEOVER'; }
interface ClickEvent { type: EventType.CLICK; } interface MouseDownEvent { type: EventType.MOUSEOVER; } declare const clickEvent: ClickEvent; declare const mouseDownEvent: MouseDownEvent; const fn3 = (event: ClickEvent) => { return event; } fn3(clickEvent); // OK fn3(mouseDownEvent); // NG
FOVN FOVNศརͰ͕͢ɺͷ߹ܕ͚ͩͰ੍ޚͰ͖ͳ͍ͷͰɺ ͱͯ͠ར༻͢Δ߹ݺͼग़͞ΕΔଆͰൣғͷνΣοΫΛ͠·͠ΐ͏ɻ
/BNFTQBDF OBNFTQBDF5ZQF4DSJQUಠࣗػೳͰ͕͢ &4.PEVMFTͷ͓͔͛Ͱ༨Γ͏ҙຯͳ͘ͳΓ·ͨ͠ ͜ͷػೳએݴϑΝΠϧҎ֎Ͱ͏ͷࠞཚͷݩͳͷͰ͏ඞཁͳ͍Ͱ ͠ΐ͏
/VMMPSVOEFpOFE KBWBTDSJQUʹͭͷແޮͳ͕͋Γ·͢ OVMMͱVOEFpOFEͰ͢ VOEFpOFE͕ະఆٛͷ߹ʹར༻͞ΕɺOVMM݁Ռ͕ଘࡏ͠ͳ͍࣌ʹ ΘΕ·͢ ͕ͦͷ͍͚ʹରͨ͠ҙຯ͋Γ·ͤΜ ࠞཚ͢Δ͚ͩͰ͢
*O5ZQF4DSJQU OVMMVOEFpOFE5ZQF4DSJQU্Ͱ໘Ͱ͢ TUJSDU/VMM$IFDLT0/ʹ͖͢Ͱ͕͢ɺVOEFpOFEͷνΣοΫ͞Ε·ͤΜ
.BZCFPS0QUJPOBM OVMMɺVOEFpOFEXSBQͯ͠͠·͍·͠ΐ͏ɹ
type Optional<T> = T | undefined | null;
0QUJPOBM ຊདྷ0QUJPOBMΫϥεʹͯ͠͠·͍͍ͨͱ͜ΖͰ͕͢ 5ZQF4DSJQUͰ0QUJPOBM$IBJOJOH͕ೖΔͷͰ ΑΓ5ZQF4DSJQUωΠςΟϒͰऔΓѻ͑Δϑϥοτͳܕͷ΄͏͕ྑ͍Ͱ͠ΐ͏
type Optional<T> = T | undefined | null; declare const
obj: Optional<{value?: string}>; // ·ͩಈ͖·ͤΜ // or obj?.value || ‘’ // force obj!.value!
࣮
%FWFMPQXJUI5ZQF4DSJQU 5ZQF4DSJQUΛͬͯ։ൃ͢Δ߹ͷ࣮खॱKBWBTDSJQUͱେ͖͘ม͑· ͠ΐ͏
*OUFSGBDF'JSTU ࠷େࣄͳ͜ͱநతͳ࣮Λ࠷ॳʹߦ͏͜ͱͰ͢ ͦΕͭ·Γ۩ମతͳϩδοΫ͔ΒΕΔ͜ͱͰ͢ 5ZQF4DSJQUJOUFSGBDFͱUZQFʹΑͬͯͦΕΛՄೳʹ͍ͯ͠·͢ ِ3FEVYΈ͍ͨͳྫΛհ͠·͢
interface Todo { id: string; date: Date; title: string; done:
boolean; } type Todos = Todo[]; interface State { todos: Todos; } type Payload = { type: "ADD", } | { type: "DELETE" payload: {id: string}; } const reducer = (payload: Payload, state: State): State => { return state; }
-PHJDJTMBUFS SFEVDFSͷ࣮Ҏ֎શͯܕͷΈͰ࣮͞Ε͍ͯ·͢ SFEVDFSதۭͰΛฦ͚ͩ͢Ͱ͢ ͔͜͠͠ΕͰϓϩάϥϜͷࠎͰ͖͍ͯ·͢ ͋ͱSFEVDFSͷ࣮ʹूத͢Δ͚ͩͰ͢
-PHJDJTMBUFS ۃͳ۩ମతͳΞϧΰϦζϜ͋·ΓॏཁͰ͋Γ·ͤΜ σʔλߏɾܕ͕ͬͱॏཁͰ͢ ͕ܾ͜͜·Εେ֓ΞϧΰϦζϜࣗવͱಋ͔Ε·͢
ڥք
7JSUVBMBOE3FBM ࠷ॳʹड़ͨΑ͏ʹ5ZQF4DSJQU͋͘·ͰԾͷܕΛ࣋ͭݴޠͰ͢ ͦͷͨΊɺ࣮ࡍʹ࣮ߦ͞ΕΔ߹ʹͱܕͷဃ͕ى͖ΔՄೳੑ͕͋Γ· ͢
4FQBSBUFE8PSME ಛʹဃ͕ى͖͍͢ͷ͕ɺ֎෦ͱͷڥքͱͳΔ෦Ͱ͢ "1*αʔόͱͷڥք ϒϥβετϨʔδͱͷڥք
"EBQUFS ͨͩ͠ɺٯʹݴ͑͜ΕΒͷڥք͑͑ͯ͞ɺઌఔͷJOUFSGBDFઌߦͷ࣮ Λߦ͑ဃΛΒ͢͜ͱ͕Ͱ͖ΔͷͰͳ͍Ͱ͠ΐ͏͔ʁ ·ͨ1SPUP#VGͷΑ͏ͳ54ࣗಈੜܥΛ͏ͷखͰ͢
1SPHSBN 1SPHSBN 1SPHSBN "EBQUFS &YUFSOBM*OUFSGBDF
$MFBO"SDIJUFDUVSF ·ΔͰ$MFBO"SDIJUFDUVSFͷϨΠϠʔਤͷΑ͏ʹͳΓ·ͨ͠ ͔͠͠ɺผʹ$MFBO"SDIJUFDUVSFΛར༻͠Ζͱݴ͍ͬͯΔΘ͚Ͱͳ͘ 5ZQF4DSJQUͷԾܕͱ͍͏Έʹͱͬͯ"EBQUFSඇৗʹॏཁͳҙຯΛ ࣋ͪ·͢ ͲΜͳΞʔΩςΫνϟΛ࠾༻͍ͯͯ͠֎෦γεςϜڥքΛਖ਼͑͘͠Δ͜ ͱͰɺ5ZQF4DSJQUͷܕΑΓҰཱͭͰ͠ΐ͏
5P5ZQFE ࠓ·Ͱͷ࠷ॳ͔Β5ZQF4DSJQUͰ։ൃ͍ͯ͠ΔέʔεΛલఏͱ͍ͯ͠·͢ ͕ ͠طଘͷKBWBTDSJQU͔ΒҠߦ͢Δ߹֎෦ڥք͔ΒܕΛ͚͍ͯ͘ͱΑ ͍Ͱ͠ΐ͏ ·ͨɺਖ਼͍͔ͨ͠ͱਖ਼͘͠ͳ͍ܕΛڥքΛه͓ͯ͘͜͠ͱ͕େࣄͰ͢
"OZBEBQUFS ܕ͚͞Ε͍ͯͳ͍ةݥͳྖҬશͯɺਖ਼͍͠ܕ͔Βมͨ͠ͱ͍͏ҹΛ ͚͓ͭͯ͘ͱϦϑΝΫλϦϯά͕͍͢͠Ͱ͢
type UncheckedFixme<T> = any; interface Model {} const unTypedFn =
(a: UncheckedFixme<Model>) { }
"OZBEBQUFS 6ODIFDLFE'JYNF5͕ͲΜͲΜίʔυͷίΞྖҬʹԡ͠ࠐ·ΕΔ·ͰϦ ϑΝΫλϦϯά͚ͭͮ͠·͠ΐ͏ ͦͯ͠࠷ޙʹίʔυத͔Βফͯ͠͠·͍·͠ΐ͏ ͜ͷΑ͏ͳ#PUUPN6Qతͳܕͷ͚ํΛ͢Δͱɺ֎෦ͷةݥͳྖҬ͔Β҆શ ͳ෦ഭ͍ͬͯ͘ͷͰܕͷϛε͕ى͖ͮΒ͍Ͱ͢ ͪͳΈʹ6ODIFDLFE'JYNF5-JOUΤϥʔग़ΔՄೳੑ͕͋ΔͷͰ௵͓ͯ͠ ͍͍ͯͩ͘͞
ίʔσΟϯά
5ZQFJTCPUIFS ܕ͚݁ߏ໘Ͱ͢ ࠷ॳʹJOUFSGBDFͰܕఆٛΛͪΌΜͱ͓ͯ͘͠ͱزจ͔ղফ͞Ε·͕͢ ຊ࣭తʹՃతͳ࡞ۀͳͷͰαϘΓ͕ͪͰ͢
.BZCFXSPOH ͨͩɺܕ͚ͷ໘͘͞͞ίʔυͷ·͔ͣ͞͠Ε·ͤΜ
class Test { private value: {[key: string]: string} | null;
constructor() {} public setValue(value: {[key: string]: string}) { this.value = value; } public doSomething() { return this.value!['key'] // you need to through type check. } }
*OJUJBMJ[FMBUFS ͜ͷΑ͏ͳޙʹॳظԽ͞ΕΔϝϯόมܕͰදݱ͢Δͷ͕ࠔͰ͢ ͞Βʹ/VMMBCMF͔VOEFpOFEΛڐ༰͢Δܕʹͨ͠߹ʹ͍͍ͪͪ Λॻ͘ͷةݥ͔ͭ໘Ͱ͢ ͜ͷΑ͏ͳɺͦͦܕͰදݱ͢Δͷ͕͍͠ίʔυΛආ͚ΔΑ͏ʹ͢Δͷ ͕ྑ͍Ͱ͢ ࠓճͷέʔεͰݴ͑શͯDPOTUSVDUPSͰॳظԽ͖͢Ͱ͢
function getValue() { let value: {[key: string]: number} | null
= null; if (x) { value = {key: 1}; } else { value = {value: 1}; } return value; }
*OJUJBMJ[FMBUFS JGจͷதͰมΛॳظԽ͢ΔͷΛ͚ͯ͞ɺJGจΛؔԽͯ͠͠·͍·͠ΐ͏
.PSFUZQBCMFDPEF ΑΓγϯϓϧʹܕ͚Ͱ͖Δίʔυ ਓؒʹಡΈ͘͢ཧղ͍͢͠ίʔυͱͳΓ·͢ ͪΖΜ͖Ε͍ʹॻ͍ͯෳࡶͳܕΛ࣋ͭέʔε͋Γ·͢͠ɺશ͕ͯͦͷ ͱ͓ΓͰ͋Γ·ͤΜ͕ ෳࡶͳܕػೳΛ͏લʹίʔυͷߏ͕ਖ਼͍͔֬͠ೝͯ͠Έ·͠ΐ͏
·ͱΊ 5ZQF4DSJQUͰͷ։ൃʹ͍ͭͯͷτʔΫͰͨ͠ ͜ΕΒͷ5JQT͕͋ͳͨͷ։ൃͷखॿ͚ʹͳΔͱ͍Ͱ͢ ͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠