Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
プロダクト開発とTypeScript
Search
Taketoshi Aono(青野健利 a.k.a brn)
October 02, 2019
Programming
3k
7
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
プロダクト開発とTypeScript
TypeScriptによるプロダクト開発の知見
Taketoshi Aono(青野健利 a.k.a brn)
October 02, 2019
More Decks by Taketoshi Aono(青野健利 a.k.a brn)
See All by Taketoshi Aono(青野健利 a.k.a brn)
document.write再考
brn
7
3.2k
Parsing Javascript
brn
14
9.6k
JSON & Object Tips
brn
1
600
CA 1Day Youth Bootcamp for Frontend LT
brn
0
1.1k
Modern TypeScript
brn
2
890
javascript - behind the scene
brn
3
820
tc39 proposals
brn
0
1k
React-Springでリッチなアニメーション
brn
1
780
javascript internationalization API
brn
0
980
Other Decks in Programming
See All in Programming
IBM Bob Dojo #1 仕様駆動開発入門
oniak3ibm
PRO
0
220
JRuby: Past, Present, and Future
headius
0
190
setup-vp GitLab対応の裏側
naokihaba
0
120
KiroのSpecで「五目並べ」を作ってみる
satoshi256kbyte
1
160
AI活用は、個人から組織へ|マルチプレイヤーエージェントハーネス「QM」の社内活用事例 / AI use is moving from individuals to orgs
rkaga
1
220
Vue Fes Japan 2026 タイムテーブル徹底解説
448jp
1
510
Agents on Rails - Rails at Scale 2026
irinanazarova
0
250
GitHubハンズオン講座 — 実務レベルのチーム開発のフローを身につけよう
junhat6
0
100
TiDB Cloudのカスタムコントローラーによるオートスケール対応
takaidohigasi
0
130
一人だけ、Kiroが静止する日
hideg
0
130
モバイル交通系ICへのチャージ実例から考える、クロスプラットフォーム開発におけるiOS実機テスト設計とCI運用
yusuga
1
540
フロントエンドUIフレームワークのこれまでとこれから
ssssota
5
2.9k
Featured
See All Featured
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
360
31k
Visualization
eitanlees
153
17k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
52
6.1k
Optimizing for Happiness
mojombo
378
71k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.9k
Practical Orchestrator
shlominoach
192
12k
Faster Mobile Websites
deanohume
310
32k
Building Flexible Design Systems
yeseniaperezcruz
330
41k
Balancing Empowerment & Direction
lara
6
1.3k
Into the Great Unknown - MozCon
thekraken
41
2.7k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
38
3k
How to Think Like a Performance Engineer
csswizardry
28
2.8k
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͕͋ͳͨͷ։ൃͷखॿ͚ʹͳΔͱ͍Ͱ͢ ͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠