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
tsconfigのオプションで変わる型世界
Search
Keisuke Ikeda
May 23, 2025
Programming
240
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
tsconfigのオプションで変わる型世界
https://2025.tskaigi.org/talks/ike_keichan
Keisuke Ikeda
May 23, 2025
More Decks by Keisuke Ikeda
See All by Keisuke Ikeda
JavaScript実装の自作プログラミング言語をTypeScript実装に移行した話
keisukeikeda
1
210
技術検証結果の整理と解析をAIに任せよう!
keisukeikeda
0
190
Docコメントで始める簡単ガードレール
keisukeikeda
1
190
初めてのLisp自作譚
keisukeikeda
0
50
Other Decks in Programming
See All in Programming
バグを直したら useEffect が消えた
colorful12
3
780
Hello, Hiroshima Geospatial Data! — Exploring DoboX with Python
ra0kley
0
140
typoなんかねぇよ
raspython3
0
630
Pythonの実行はどこまで賢くなったのか? CPythonとPyPyから見る最適化のしくみ
curekoshimizu
4
2.3k
業務時間外もAIに働いてもらう話
colorful12
3
9.4k
【DroidKaigi 2026】「アクセシビリティを利用するとき、 アクセシビリティもまたこちらを利用している」 〜マルウェアによる攻撃と防衛について〜
halunoyo
0
110
GKE アップグレード前に知っておきたい Blue/Green と PDB の関係
stkk
0
120
実装をデザインガイドラインに追従させるための取り組み / 260731-dip-mosh-design-system
dachi023
0
8k
Cloudflare is Agents
chimame
0
190
いまどきの Codex で開発する visionOS アプリの開発スタイルについて
karad
0
170
ソフトウェアエンジニアにとっての生成AI - 特性を知って使い倒す / generative ai for software enginner
kishida
7
2.3k
Loosening the Reins: Go Generics Get More Flexible
kuro_kurorrr
0
360
Featured
See All Featured
Designing Powerful Visuals for Engaging Learning
tmiket
1
520
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
508
140k
Six Lessons from altMBA
skipperchong
29
4.5k
Code Reviewing Like a Champion
maltzj
528
40k
jQuery: Nuts, Bolts and Bling
dougneiner
66
8.6k
Everyday Curiosity
cassininazir
0
300
Color Theory Basics | Prateek | Gurzu
gurzu
0
450
KATA
mclloyd
PRO
35
15k
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.8k
Claude Code どこまでも/ Claude Code Everywhere
nwiizo
67
57k
How to Build an AI Search Optimization Roadmap - Criteria and Steps to Take #SEOIRL
aleyda
1
2.2k
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
141
35k
Transcript
UTDPOGJHͷΦϓγϣϯͰ มΘΔܕੈք ,FJTVLF*LFEB 54,BJHJ !JLF@LFJDIBO
自己紹介 02/16 ,FJTVLF*LFEB ɾ౦ژͱؔʢେࡕ&ژʣͷ2ڌੜ׆த ɾTSKaigi 2025, ϑϩϯτΤϯυΧϯϑΝϨϯεؔ 2025ͷελοϑ ɾษڧձେ͖Ϛϯ, ษڧձதͷπΠʔτ͕͏Δ͍͞
ɾ࠷ۙί̋μᘖᘣͷϞʔχϯάʹϋϚͬͯΔ
tsconfigに向き合おう! 03/16 tsconfig ΛͪΌΜͱݟͨ͜ͱ͋Γ·͔͢ʁ
tsconfigに向き合おう! 04/16 ɾσϑΥϧτઃఆͰͷӡ༻ ɾࣗͷϙδγϣϯతʹؔΘΔػձ͕ͳ͍ ɾϓϩδΣΫτͷ్தࢀըͷͨΊઃఆෆཁ ɾ࠷ॳʹઃఆͯ͠Ҏ߱ɺݟ͞ͳ͍ ɾֶशͰߏจܕͷॻ͖ํͳͲ͕༏ઌ ɾଞπʔϧͷઃఆʹຒΕ͍ͯΔ UTDPOGJH͕ݟա͝͞Ε͕ͪͳཧ༝ ֶͿɾݟ͢ػձͷܽɹ
tsconfigに向き合おう! 05/16 ͜ͷൃදͰߦ͏͜ͱ ɾॳ৺ऀ͚ʹֶͿɾݟͨ͢Ίͷ͖͔͚ͬΛఏڙ ɾ۩ମతʹʁ ɹ- ॳظઃఆʢtsc --initʣͷ tsconfig.json ΛϕʔεʹɺҰ෦ͷΦϓγϣϯ
ɹɹΛมߋ͠ɺ͋͑ͯʮܕʯΛ؇ ɹ- ઃఆͷมߋͰܕ҆શੑ͕Ͳ͏มΘΔ͔Λݕূ ɾʮܕͷ͋Γ͕ͨΈʯͱʮઃఆͷॏཁੑʯΛ࣮ײ
tsconfigに向き合おう! 06/16 ͜ͷLTͰ tsconfig ΛֶͿɾݟ͖͔͚ͬ͢ʹʂ ʢͳΕخ͍͠ʣ
5ZQF4DSJQU%PDVNFOUBUJPOʮ$PNQJMFS0QUJPOTʯ ݄Ҿ༻ IUUQTXXXUZQFTDSJQUMBOHPSHKBUTDPOGJH オプションによる変化 07/16 ܕʹؔ͢ΔΦϓγϣϯ ݱࡏʢʣશ෦ͰΦϓγϣϯ
45&1ɿॳظঢ়ଶ index.ts オプションによる変化 08/16 type User = { id: number;
name: string; }; class UserManager { // TS2564:プロパティが未初期化 private users: User[]; // TS7006:引数が暗黙的にany型 addUser(user) { this.users.push(user); return user.id; } findUserById(id: number): User | null { const foundUser = this.users.find((user) => user.id === id); // TS2322:型の不一致 "User | undefined"型 return foundUser; } getUserName(id: number): string { const user = this.findUserById(id); // TS18047:usersがnullable return user.name; } } tsconfig.json { "compilerOptions": { "target": "es2016", "module": "commonjs", "esModuleInterop": true, "strict": true, "skipLibCheck": true, "outDir": "./dist" }, "include": ["src/*.ts"], "exclude": ["node_modules"] }
45&1ɿॳظঢ়ଶ index.ts オプションによる変化 09/16 type User = { id: number;
name: string; }; class UserManager { // TS2564:プロパティが未初期化 private users: User[]; // TS7006:引数が暗黙的にany型 addUser(user) { this.users.push(user); return user.id; } findUserById(id: number): User | null { const foundUser = this.users.find((user) => user.id === id); // TS2322:型の不一致 "User | undefined"型 return foundUser; } getUserName(id: number): string { const user = this.findUserById(id); // TS18047:usersがnullable return user.name; } } tsconfig.json { "compilerOptions": { "target": "es2016", "module": "commonjs", "esModuleInterop": true, "strict": true, "skipLibCheck": true, "outDir": "./dist" }, "include": ["src/*.ts"], "exclude": ["node_modules"] } 54ϓϩύςΟ͕ະॳظԽ 54Ҿ͕҉తʹBOZܕ 54ܕͷෆҰகʢOVMMͱVOEFGJOFEͷ۠ผʣ 54ฦΓ͕OVMMBCMF
มߋ͢ΔͭͷΦϓγϣϯ オプションによる変化 10/16 ɾstrictPropertyInitialization ɹ- ΫϥεͷϓϩύςΟ͕ॳظԽ͞Ε͍ͯΔ͔ΛνΣοΫ ɾstrictNullChecks ɹ- null ͱ
undefined Λݫີʹ۠ผ&νΣοΫ ɾnoImplicitAny ɹ- ҉తʹ any ܕΛνΣοΫ
45&1ɿϓϩύςΟॳظԽνΣοΫແޮ index.ts オプションによる変化 11/16 type User = { id: number;
name: string; }; class UserManager { // TS2564:プロパティが未初期化 private users: User[]; // TS7006:引数が暗黙的にany型 addUser(user) { this.users.push(user); return user.id; } findUserById(id: number): User | null { const foundUser = this.users.find((user) => user.id === id); // TS2322:型の不一致 "User | undefined"型 return foundUser; } getUserName(id: number): string { const user = this.findUserById(id); // TS18047:usersがnullable return user.name; } } tsconfig.json { "compilerOptions": { "target": "es2016", "module": "commonjs", "esModuleInterop": true, "strict": true, + "strictPropertyInitialization": false, "skipLibCheck": true, "outDir": "./dist" }, "include": ["src/*.ts"], "exclude": ["node_modules"] } Τϥʔআ
45&1ɿOVMMͱVOEFGJOFEͷݫີͳ۠ผˍνΣοΫແޮ index.ts オプションによる変化 12/16 type User = { id: number;
name: string; }; class UserManager { // TS2564:プロパティが未初期化 private users: User[]; // TS7006:引数が暗黙的にany型 addUser(user) { this.users.push(user); return user.id; } findUserById(id: number): User | null { const foundUser = this.users.find((user) => user.id === id); // TS2322:型の不一致 "User | undefined"型 return foundUser; } getUserName(id: number): string { const user = this.findUserById(id); // TS18047:usersがnullable return user.name; } } tsconfig.json { "compilerOptions": { "target": "es2016", "module": "commonjs", "esModuleInterop": true, "strict": true, "strictPropertyInitialization": false, + "strictNullChecks": false, "skipLibCheck": true, "outDir": "./dist" }, "include": ["src/*.ts"], "exclude": ["node_modules"] } Τϥʔআ Τϥʔআ
45&1ɿ҉తͳBOZܕͷνΣοΫແޮ index.ts オプションによる変化 13/16 type User = { id: number;
name: string; }; class UserManager { // TS2564:プロパティが未初期化 private users: User[]; // TS7006:引数が暗黙的にany型 addUser(user) { this.users.push(user); return user.id; } findUserById(id: number): User | null { const foundUser = this.users.find((user) => user.id === id); // TS2322:型の不一致 "User | undefined"型 return foundUser; } getUserName(id: number): string { const user = this.findUserById(id); // TS18047:usersがnullable return user.name; } } tsconfig.json { "compilerOptions": { "target": "es2016", "module": "commonjs", "esModuleInterop": true, "strict": true, "strictPropertyInitialization": false, "strictNullChecks": false, + "noImplicitAny": false, "skipLibCheck": true, "outDir": "./dist" }, "include": ["src/*.ts"], "exclude": ["node_modules"] } Τϥʔআ ίϯύΠϧ࣌ͷΤϥʔ͕શͯফ͑ͯ͠·ͬͨ…
࣮ߦͰ͖ͳ͍ϓϩάϥϜ index.ts オプションによる変化 14/16 const manager = new UserManager(); //
strictPropertyInitialization:falseにより見落とされるエラー // 実行時エラー: Cannot read properties of undefined (reading 'push') const user = { id: 1, name: '山田太郎' }; manager.addUser(user); // strictNullChecks:falseにより見落とされるエラー // 実行時エラー: Cannot read properties of undefined (reading 'find') const nonExistentUser = manager.findUserById(999); // noImplicitAny:falseにより見落とされる不具合 // 実行エラーにもならず許容されてしまう。 const incompleteUser = { name: true }; manager.addUser(incompleteUser);
オプションによる変化 15/16 ͦͷΦϓγϣϯʢͷมߋʣඞཁ͔ʁ ɾྫʹڍ͛ͨΦϓγϣϯΛΓସ͑Δඞཁ͕͋Δͷ͔ʁ ɹ- શͯͷϓϩδΣΫτ͕࠷৽ͷόʔδϣϯϕετϓϥΫςΟεʹͰ͖ͯ ɹɹ͍ΔΘ͚Ͱͳ͍ɻ ɹ- TypeScriptҠߦதͷϓϩδΣΫτͰஈ֊తʹಋೖ͍ͯ͠Δ߹ͳͲ ɹɹڐ༰ͤ͟ΔΛಘͳ͍͜ͱ͋Δɻ
ɾԿ͔͠Βͷधཁ͕͋Δ͔ΒΦϓγϣϯଘࡏ͍ͯ͠Δɻ
まとめ 16/16 ·ͱΊ ɾࠓճڍ͛ͨΦϓγϣϯҎ֎ʹ100ݸҎ্ͷΦϓγϣϯ͕ଘࡏ ɹ- ΑΓྑ͍ઃఆΛ͢ΔͨΊʹ֮͑Δඞཁͳ͍͕ɺ ɹɹͬ͘͟ΓͲΜͳछྨͷΦϓγϣϯ͕ଘࡏ͢Δ͔Δ͜ͱ͕େࣄʂ ɾෆཁʹࢥ͑ΔΦϓγϣϯϓϩδΣΫτʹΑͬͯඞཁʂ ɾϓϩδΣΫτຖʹదͳઃఆΛʂtsconfigΛઃఆͯ͘͠Εͨਓʹײँʂ
宣伝 ϑϩϯτΤϯυΧϯϑΝϨϯεؔ 2025 ଓใSNSͰ֬͝ೝ͍ͩ͘͞ʂ Xɿhttps://x.com/fec_kansai Blueskyɿhttps://bsky.app/profile/fec-kansai.bsky.social