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.8k
プロダクト開発と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
13
9.1k
JSON & Object Tips
brn
1
440
CA 1Day Youth Bootcamp for Frontend LT
brn
0
870
Modern TypeScript
brn
2
770
javascript - behind the scene
brn
3
710
tc39 proposals
brn
0
820
React-Springでリッチなアニメーション
brn
1
650
javascript internationalization API
brn
0
840
Other Decks in Programming
See All in Programming
昭和の職場からアジャイルの世界へ
kumagoro95
1
380
チームリードになって変わったこと
isaka1022
0
200
Grafana Cloudとソラカメ
devoc
0
170
パスキーのすべて ── 導入・UX設計・実装の紹介 / 20250213 パスキー開発者の集い
kuralab
3
780
pylint custom ruleで始めるレビュー自動化
shogoujiie
0
120
color-scheme: light dark; を完全に理解する
uhyo
3
310
『GO』アプリ バックエンドサーバのコスト削減
mot_techtalk
0
140
iOSエンジニアから始める visionOS アプリ開発
nao_randd
3
130
GoとPHPのインターフェイスの違い
shimabox
2
190
WebDriver BiDiとは何なのか
yotahada3
1
140
社内フレームワークとその依存性解決 / in-house framework and its dependency management
vvakame
1
560
Rubyで始める関数型ドメインモデリング
shogo_tksk
0
110
Featured
See All Featured
KATA
mclloyd
29
14k
What's in a price? How to price your products and services
michaelherold
244
12k
Typedesign – Prime Four
hannesfritz
40
2.5k
Optimizing for Happiness
mojombo
376
70k
Art, The Web, and Tiny UX
lynnandtonic
298
20k
Fashionably flexible responsive web design (full day workshop)
malarkey
406
66k
Gamification - CAS2011
davidbonilla
80
5.1k
Building a Scalable Design System with Sketch
lauravandoore
461
33k
Designing for Performance
lara
604
68k
The Cult of Friendly URLs
andyhume
78
6.2k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
248
1.3M
Building Adaptive Systems
keathley
40
2.4k
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͕͋ͳͨͷ։ൃͷखॿ͚ʹͳΔͱ͍Ͱ͢ ͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠