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
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Saji
May 21, 2026
Technology
160
0
Share
業務に残された「良くない型」で考える「TypeScriptの難しさ」
TSKaigi2026
-
https://2026.tskaigi.org/talks/5
X
-
https://twitter.com/sajikix
Saji
May 21, 2026
More Decks by Saji
See All by Saji
It’s “Time” to use Temporal
sajikix
3
300
ユーザーが作成したコードをブラウザ上で安全に実行できる Plugin システムへのアプローチ
sajikix
1
650
Branded Typesで日時の複雑さと戦う
sajikix
4
1.2k
推しProposalと広がる夢~Intl.MessageFormatとDomLocalization~
sajikix
1
640
自作JSエンジンに推しプロポーザルを実装したい!
sajikix
1
340
Lookback TypeScript ESM support and what should we do now.
sajikix
5
790
フロントエンドで日時処理と戦うために 2025 ver
sajikix
6
4.6k
先取り!Temporal
sajikix
0
310
アプリ文言のパースで学ぶ 文字列Literal型パズル入門
sajikix
3
1.3k
Other Decks in Technology
See All in Technology
"スキルファースト"で作る、AIの自走環境
subroh0508
0
570
Databricks 月刊サービスアップデートまとめ 2026年04月号
tyosi1212
0
130
20260515 ⾃分のアカウントとプライバシーを守る認証と認可の話〜利⽤者向け〜
oidfj
0
660
JTCでRedmine利用者2700人を実現した手法 第二部
nobuonakamura
0
120
マンション備え付けのネットワークとLTE回線を組み合わせた ネットワークの安定化の考案
harutiro
1
130
M&Aで増え続けるプロダクトに少数QAはどう立ち向かうか─GENDAが挑む、全員で取り組む品質標準化戦略 / GENDA Tech Talk #4
genda
0
110
AI 時代の Platform Engineering
recruitengineers
PRO
1
210
freeeで運用しているAIQAについて
qatonchan
1
630
20260515 ログイン機能だけではないアカウント管理を全体で考える~サービス設計者向け~
oidfj
1
710
Every Conversation Counts
kawaguti
PRO
0
240
PdM・Eng・QAで進めるAI駆動開発の現在地/aidd-with-pdm-eng-qa
shota_kusaba
0
250
AI対話分析の夢と、汚いデータの現実 Looker / Dataplex / Dataform で実現する品質ファーストな基盤設計
waiwai2111
0
620
Featured
See All Featured
Agile Actions for Facilitating Distributed Teams - ADO2019
mkilby
0
190
The MySQL Ecosystem @ GitHub 2015
samlambert
251
13k
Un-Boring Meetings
codingconduct
0
290
How to Grow Your eCommerce with AI & Automation
katarinadahlin
PRO
1
180
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
659
62k
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
194
17k
HDC tutorial
michielstock
2
660
Heart Work Chapter 1 - Part 1
lfama
PRO
7
35k
Building a Scalable Design System with Sketch
lauravandoore
463
34k
Darren the Foodie - Storyboard
khoart
PRO
3
3.3k
Visual Storytelling: How to be a Superhuman Communicator
reverentgeek
2
530
For a Future-Friendly Web
brad_frost
183
10k
Transcript
3ZVTFJ4BKJLJ!TBKJLJY ۀʹ͞Εͨʮྑ͘ͳ͍ܕʯͰߟ͑Δ ʮ5ZQF4DSJQUͷ͠͞ʯ
4BKJ3ZVTFJ4BKJLJ 'SPOUFOE%FWFMPQFSBU$ZCP[V JOD ❤54JO'&5PPMT 𝕏 !TBKJLJY
ޭʹύλʔϯͳ͍͕ ࣦഊʹύλʔϯ͕͋Δ Έ͍ͨͳ֨ݴ͋Δ͡Όͳ͍Ͱ͔͢
5ZQF4DSJQUͰߟ͑Δͱʁ ࣦഊΑ͘ͳ͍ͱ͞Ε͍ͯΔܕه๏ɾଥڠͨ͠ͱ͜Ζ ˣͱ͢Δͱ Ծઆ̍ʮ5ZQF4DSJQUͰଥڠɾϛεͪ͠ΌͬͯΔͱ͜Ζʹύλʔϯ͕͋Δʯ ˣ͞Βʹݴ͑ Ծઆ̎ʮ͜ͷύλʔϯ͕ͦ͜5ZQF4DSJQUͷ͠͞PSݶքͳͷͰʯ
ΞδΣϯμ w ʮۀͰॻ͍ͯ͠·ͬͨྑ͘ͳ͍ܕɾଥڠͨ͠ܕΛऩूɾྨʯͯ͠ɺ w ͦΕΒΛʮύλʔϯԽɾੳ͢Δ͜ͱʯͰɺ w 5ZQF4DSJQUͷ͠͞ͷҰʹഭΖ͏ʂ ͱ͍͏τʔΫͰ͢ʂՃ͑ͯɺ w 5ZQF4DSJQUΛֶͿɾڭ͑Δɾ"*ʹॻ͔ͤΔࡍͷώϯτΛఏڙ͠ɺ
w ༷ʑͳϊϋݟ͕ू·Δͱ͍ͨ͠
ҙࣄ߲⚠ ʮ͜Μͳܕॻ͍ͯΔͳΜͯμϝʂʯͱݴ͏τʔΫͰ͋Γ·ͤΜʂ େࣄ w ୭ͩͬͯΜͰas@ts-ignoreͯ͠ΔΘ͚͡Όͳ͍ w ࣗͩͬͯଟগͨ͜͠ͱ͋ΔͰ͠ΐʁ ڳʹखΛͯͳ͕Β
্ڃऀͷํʹͱͬͯͨΓલͷ͜ͱଟ͍͔͠Ε·ͤΜ͕ɺ w ॳ৺Λࢥ͍ग़ͨ͠Γɺͬͱ͍͍ղܾࡦΛߟ͑ͯΈͨΓ w νʔϜͰͷӡ༻ɾޙਐҭɾ"*͚%PDͳͲ׆͔ͤΔͱ͋͜Δͣ
࣍ ϓϩμΫτͷʮྑ͘ͳ͍ܕʯΛ୳ͯ͠ΈΑ͏ සग़ྫɾ͍͠ྫͷհ ʮྑ͘ͳ͍ܕʯΛྨ͢Δ ݟ͔Βӡ༻
࣍ ϓϩμΫτͷʮྑ͘ͳ͍ܕʯΛ୳ͯ͠ΈΑ͏ සग़ྫɾ͍͠ྫͷհ ʮྑ͘ͳ͍ܕʯΛྨ͢Δ ݟ͔Βӡ༻
Ͳ͜·ͰΛྑ͘ͳ͍ܕͱ͢Δ͔ Ұൠతʹྑ͘ͳ͍ͱ͞ΕΔͷ w anyܕ w asʹΑΔڧ੍Ωϟετ w @ts-ignoreʹΑΔܕνΣοΫͷແࢹ ্ه΄ͲͰͳ͍͕ྑ͘ͳ͍ͱ͞ΕͯΔ w
ࡶͳܕΨʔυؔ
ࠓճରʹͨ͠ίʔυϕʔεͷಛ Ұൠత 3FBDU54ͷҰൠతͳ$MJFOU4JEFΞϓϦߏ ෳࡶͳ'PSNը໘ ೖྗͨ͠σʔλ Ϩίʔυ ͷՄࢹԽ w Ϣʔβʔ͕༷ʑͳ'JFMEͰߏஙͨ͠'PSNΛ࣮ࡍʹಈ࡞ͤ͞Δ w
ೖྗͨ͠σʔλͷৄࡉදࣔҰཡɾάϥϑදࣔɾߜΓࠐΈͳͲ͕Ͱ͖Δ #&͔Βͷσʔλجຊతʹ;PEͰ7BMJEBUJPOͯ͠Δ ͬͯΔਓ͚LJOUPOFͷΞϓϦը໘ͷ3FBDU൛
ࠓճରʹͨ͠ίʔυϕʔεͷಛ ಛघ ͔ͨ͠͠ΒҰൠతͰͳ͍͔͠Εͳ͍ཁ݅ w 'PSN͕ͦΕͳΓʹෳࡶ w fi FMEͷछྨׂ͕ͱଟ͍ छྨҎ্
w ςʔϒϧͷதʹ fi FMEΛஔͰ͖ΔͷͰ̍ஈͷ࠶ىతͳߏ͕͋Δ w Λ+4Ͱॻ͍ͨ6TFS4DSJQU1MVHJOͰΧελϚΠζͰ͖Δػߏ w Ϣʔβʔೖྗͱ#&͔ΒͷσʔλҎ֎ʹ৴པͰ͖ͳ͍ڥք͕͋Δ w ྫ Ϣʔβ͔Β͞Εͨ$BMMCBDLͷݺͼग़͠ͱ͔
୳͠ํ ୳ͤ͞ํ ࠓͷ࣌"*͕͋ΔͷͰੵۃతʹ׆༻͠Α͏ʂ ҎԼΛूதͯ͠ཏతʹ୳ͤͨ͞ w @ts-ignore@ts-expect-error w asΩϟετ as constas
unknown asΛআ֎ w ܕΨʔυؔvalue is X ͋Δఔࡉ͔͘ྨͤ͞Δˠྨ͝ͱʹ࣮ࡍʹίʔυΛݟͯஅ
࣍ ϓϩμΫτͷʮྑ͘ͳ͍ܕʯΛ୳ͯ͠ΈΑ͏ සग़ྫɾ͍͠ྫͷհ ʮྑ͘ͳ͍ܕʯΛྨ͢Δ ݟ͔Βӡ༻
ࠓճ̓ͭසग़ྫΛհ ಛघͳͷɾϨΞ͗͢ΔͷΛൈ͍ͯ̓ͭͷසग़ྫΛհ͢Δ w ͦΕͧΕʹରͯ͠ߟ͑ΒΕΔରࡦซͤͯ ਐΊ͍͢Α͏ʹେ͖̏ͭ͘ͷύλʔϯʹྨͯ͠հ w ͩΜͩΜͱॳาతˠ͍͜͠ʹͳ͍͖ͬͯ·͢ ˞͋͘·ͰࣗνʔϜͷੳ݁ՌͳͷͰѱ͔͠Βͣ
සग़ύλʔϯ ಈతͳڥքͰͷܕམͪ
සग़%0.&WFOUDBUDI F %0.&WFOUCVCCMJOHͷͨΊʹͲ͏ͯ͠ܕ͍ &SSPSΠϯελϯε+4ͷ্༷string͛ΕΔͷͰunknown button.addEventListener('click', (e) => { const target
= e.target as HTMLButtonElement; // ← as }); try { ... } catch (e) { console.error((e as Error).message); // ← as }
සग़%0.&WFOUDBUDI F վળҰखؒͰߜΓࠐΊΔͷͰؤுΖ͏ w %0.&WFOUDVSSFOU5BSHFUΛ͏e instanceofͰOBSSPX w DBUDI F ܕΨʔυΛڞ௨Խͯ͠Α͍
export function isError(value: unknown): value is Error { return value instanceof Error; }
සग़VOLOPXOͰBTͯ͠·͏ ͱΓ͋͑ͣͦΕͬΆ͍ܕ΄͍͠ˠVOLOPXOؚ͕·Ε͍ͯΔBTͪ͠ΌͬͯΔ w ϓϩμΫγϣϯίʔυҎ֎ UFTUͱ͔ ͩͱ͋ͬͨΓ͢Δ վળܕΨʔυΛॻ͜͏ w ϓϩμΫγϣϯίʔυͷ߹ɺͦ͜ΛڥքʹӨڹ͕ٴ͢Δ w
νʔϜ PS"*%PD ͰͪΌΜͱنʹ͢Δͷ͋Γ const value = (config as Record<string, unknown>)[key];
සग़จࣈྻˠ#SBOEFEܕϦςϥϧܕͷݶք ҎԼͷΑ͏ͳΑΓݫ͍͠ߜΓࠐΈσϑΥϧτͰͰ͖ͳ͍ w ͍ΘΏΔ#SBOEFEܕͷΑ͏ͳಠࣗఆٛͷΑΓݫ͍͠ܕ w SVOUJNFͷϝιουجຊจࣈྻϦςϥϧܕ·ͰߜΓࠐΊͳ͍ if (regex.test(rawString)) { return
rawString as DateString; // ← as } const lower = value.toLowerCase(); // → string return lower as LowerValue; // ← as
සग़จࣈྻˠ#SBOEFEܕϦςϥϧܕͷݶք վળܕΨʔυΛॻ͘IFMQFSͷಋೖ w regex.testͳͲܕΨʔυؔΛॻ͔͘͠ͳ͍ w -PXFS$BTFͳͲͷϢʔςΟϦςΟ͕͋ΔIFMQFSʹͪ͠Ό͏ toLower<T extends string>(s: T):
Lowercase<T>
ύλʔϯ̍ͷ·ͱΊ w ೖྗɾΤϥʔͳͲͷಈతڥքͰVOLOPXOͳܕຊདྷΑΓ͍ܕ͕ݱΕΔ w ·ͨඪ४ϝιουͰQSJNJUJWFͳܕҎ্ͷߜΓࠐΈ͍͠ w ͜ͷΑ͏ͳBTʮܕΨʔυPSϔϧύʔݸʯͰ͋Δఔ҆શʹফͤΔ w ͲͪΒ͔ͱ͍͏ͱਓతͳཧ༝͕ଟ͍ w
ʮ໘Ͱʯݟա͝͞Εͨ w ఆͷͣͷͷ͕ͬͯ͠·ͬͨ
සग़ύλʔϯ ಈతͳྻɾ0CKFDUม
සग़"SSBZGJMUFSJODMVEFTJT"SSBZ "SSBZͷඪ४ϝιουͰ͋ΔincludesisArrayͳͲ·ͩෆศ͕͞Δ w JODMVEFTSFBE0OMZ"SSBZͩͱϦςϥϧܕΛڧ੍ w ͔ͱ͍ͬͯɺ௨ৗͷϓϦϛςΟϒͳྻʹ͢ΔͱͨΓલʹܕ͕མͪΔ const STATES = ['a',
'b'] as const; STATES.includes(state); // state: string ͰܕΤϥʔ STATES.includes(state as 'a' | 'b'); // ← ଆͰ as const fieldTypes : string = ['a', 'b']; return fieldTypes.includes(field.type) ? {...field} as Field : null // typestringͷ··ͳͷͰ
සग़"SSBZGJMUFSJODMVEFTJT"SSBZ w JT"SSBZཁૉܕΛ࣋ͨͳ͍ ˠ͜ͷଞɺ"SSBZͷඪ४ϝιου͕Ͳ͜·ͰߜΓࠐΜͰ͘ΕΔ͔ҙ͕ඞཁ Array.isArray(value) ? (value as JsApiUserData[]) :
[]
සग़"SSBZGJMUFSJODMVEFTJT"SSBZ ͱ͍͑গͣͭ͠ਪվળ͞Ε͍ͯΔ w 54Ͱ fi MUFS͕վળ͞Εͨͷͱ͔ʹͳͬͨ w FWFSZಉ༷ʹվળͯ͠Δ [1, 2,
null].filter((x) => x !== null); // ~5.4: (number | null)[] // 5.5~: number[] ← inferred type predicate
සग़"SSBZGJMUFSJODMVEFTJT"SSBZ վળϔϧύʔΛ࡞ΔܕΨʔυΛॻ͘ w JODMVEFTϔϧύʔΛॻ͍ͯͦΕΛ͏Α͏ʹ͢Δ w JT"SSBZ.every(isXXX)Ͱཁૉ୯ҐͷܕΨʔυΛॻ͘ function includesType<T extends readonly
string[]>( arr: T, v: string ): v is T[number] { return arr.includes(v); } const users = Array.isArray(value) && value.every(isUser) ? value : [];
සग़"SSBZGJMUFSJODMVEFTJT"SSBZ վળϥΠϒϥϦͷར༻ߟ͑ͯΈΔ w UTSFTFUͱ͍͏ඪ४ϝιουΑΓڧݻͳIFMQFSΛఏڙ͢ΔϥΠϒϥϦ͋Δ w IUUQTHJUIVCDPNNBUUQPDPDLUTSFTFU import '@total-typescript/ts-reset/array-includes'; const users
= ['matt', 'sofia', 'waqas'] as const; // .includes ୯ʹstringΛظ͢ΔΑ͏ʹͳΔ users.includes('bryan');
සग़0CKFDUGSPN&OUSJFT0CKFDULFZT ߏత෦ܕͷݶքͱͯ͠0CKFDUࠪܥͷϝιουΓ͕ྼԽ͢Δ w ˠܕʹॻ͍͍ͯͳ͍ΩʔΛ࣋ͭPCKFDUಉ͡ܕͱͯ͠௨Γ͏Δ const obj = Object.fromEntries(entries); // ↑
Record<string, V> (ΩʔϦςϥϧ͕ফ͑Δ) Object.keys(record).forEach((k) => { record[k]; // ← k stringɺkeyof typeof record ʹͳΒͳ͍ });
සग़0CKFDUGSPN&OUSJFT0CKFDULFZT վળIFMQFSΛ࡞Γ݈ͭͭશੑࣗͨͪͰอূ͢Δ w GSPN&OUSJFTΩʔͱͷηοτͰอূ͢ΔIFMQFSΛ࡞Γͭͭݕূ w LFZTܕҾ͔Βਪ͢ΔIFMQFS࡞Γͭͭݕূ ͲͪΒʹͤΑɺ҆શੑϢʔβͰอূ͢Δ͔͠ͳ͍ fromEntriesTyped<K, V>(entries: [K,
V][]): Record<K, V> objectKeys<T>(o: T): (keyof T)[] // (தͰ as)
ύλʔϯ̎ͷ·ͱΊ w "SSBZ0CKFDUͷඪ४ϝιουʹؔͯ͠ɺͲ͏ͯ͠୯ମͰղܾ͍͠ w ඪ४ϝιουʹର͢Δઃܭஅ w ߏత෦ܕʹΑΔݶք w ࣗ࡞ϔϧύʔܕΨʔυͰ͋Δఔޮతʹ҆શଆʹͤΔ w
Α͘͏ͷڞ௨Խ͓ͯ͘͠ͱΈΜͳ͕Ըܙʹ༬͔ΕΔ w ͨͩ͠OBSSPXJOHܕΨʔυϢʔβʔ࣍ୈͳ෦͕େ͖͍ͷͰ৻ॏʹ
සग़ύλʔϯ VOJPOͷѻ͍ͷ͠͞
͓͞Β͍EJTDSJNJOBUFEVOJPO 54ʹEJTDSJNJOBUFEVOJPOͱ͍͏ڧྗͳਪػೳ͕͋Δ w VOJPOʹଐ͢Δ0CKFDUʹڞ௨͢ΔϓϩύςΟͰVOJPOΛߜΓࠐΊΔػೳ type Field = | { type:
'TEXT'; value: string } // ← discriminant: type | { type: 'NUMBER'; value: number }; function show(f: Field) { if(f.type === "TEXT") return f.value; // string ʹ narrow }
සग़ରԠ͍ͤͨ͞ΛผʹΈཱͯͯ͠·͏ ຊདྷ̍ର̍ͰରԠ͍ͤͨ͞ܕΛผʑʹ࡞ͯ͠͠·͏ w ޙ͔ΒͦΕͧΕͷରԠؔΛิ͢Δ͜ͱͰ͖ͳ͍ w ܕͱͯ͠୯७ͳੵʹͳͬͯ͠·͏ w const fieldType =
MAPPING[type]; // ผͷࣜͰܭࢉ const fieldValue = convertValue(fieldValue); // ผͷࣜͰܭࢉ const field = { type: jsApiFieldType, value: jsApiValue, } as Field; // Fieldʹas͢Δ͔͠ͳ͘ͳΔ
සग़ରԠ͍ͤͨ͞ΛผʹΈཱͯͯ͠·͏ TUSJOH OVNCFS 5&95 ✅ /6.#&3 ✅ TUSJOH OVNCFS 5&95
✅ ❌ /6.#&3 ❌ ✅ {type:'TEXT',value:string} {type:'NUMBER',value:number} type: 'TEXT' | 'NUMBER', value: string | number ✅ཉ͔ͬͨ͠ܕ EVOJPO ❌࣮ࡍͷܕ ੵ
සग़ରԠ͍ͤͨ͞ΛผʹΈཱͯΔ վળઃܭ্ߏஙΛผʑʹ͠ͳ͍ w GBDUPSZͷΑ͏ͳܗͰରԠ͍ͤͨ͞ͷΛηοτͰߏங͠Δ function createField(typeInput,fieldInput): Field { switch (typeInput)
{ case 'TEXT': return { type: 'TEXT', value: String(fieldInput) }; // ... } }
සग़Ҿͷ6OJPO͔ΒฦΓΛਪͮ͠Β͍ ʮҾͷܕʹԠͯ͡ฦΓͷܕΛม͑ΔؔʯΛδΣωϦοΫʹॻ͚ͳ͍ w 5<UZQF>ͷΑ͏ͳδΣωϦοΫͳJOEFYFEBDDFTTVOJPOʹͳΔ w ˠؔຊମͰʮ5͕'JFME"͔'JFME#͔ʯ͕ఆ·Βͳ͍ function validate<T extends FieldA
| FieldB>( value: unknown, type: T['type'] ): Result<T> { return ok({ value: String(value), type } as T); // ^^^^ ← as }
සग़Ҿͷ6OJPO͔ΒฦΓΛਪͮ͠Β͍ ղܾPWFSMPBEؔͰͳΜͱ͔͢Δ ͱ͍͑ɺύλʔϯ͕૿͑ΔͱΤϥʔ͕গ͠Θ͔Γʹ͍͘ function validate(v: unknown, t: 'TEXT' ): Result<FieldA>;
function validate(v: unknown, t: 'NUMBER'): Result<FieldB>; function validate(v: unknown, t: string): Result<FieldA | FieldB> { return ok({ value: String(v), type: t }); }
සग़ δΣωϦοΫͳҾͰϋϯυϥΛݺͿ ҎԼͷΑ͏ͳΈΛ࡞Δ͜ͱΛ૾ͯ͠΄͍͠ w LFZΛࢦఆͯ͠ϋϯυϥʔؔΛಈతʹొͰ͖ɺݺͼग़͞ΕΔ w ྫFWFOU໊Λࢦఆͯ͠ΠϕϯτϋϯυϥΛొ w LFZʹԠͯ͡ҎԼ͕มΘΔ w
ϋϯυϥʔʹ͢Ҿ w ϋϯυϥʔ͕ฦͣ͢ͷฦΓ
සग़ δΣωϦοΫͳҾͰϋϯυϥΛݺͿ ͬ͘͟Γ࣮ͯ͠ΈΔͱ͜͏ͳΓͦ͏ type Apis = { "getId" :() =>string
.... } const callHandler = async <K extends keyof Apis>({ apiPath, // K apiArgs // Parameters<Apis[K]> }: JsApiCallData[K]) => { const handler = apiHandlers[apiPath]; // Apis[K] return await handler(...apiArgs); // Τϥʔ !! };
සग़ δΣωϦοΫͳҾͰDBMMCBDLΛݺͿ ͳΜͰΤϥʔʹͳͬͯΔͷ͔ w ࣮ΛݟΔͱ w LFZ͔ΒҾ͍͖ͯͨϋϯυϥͷܕ֤ϋϯυϥ ؔ ͷ6OJPOApis[K] w
Ҿϋϯυϥ͕ظ͢ΔҾͷ6OJPOParameters<Apis[K]> w ొ͞Εͨϋϯυϥ͕ड͚͚ΔҾܕશҾܕͷJOUFSTFDUJPO ม w ʮશҾܕͷJOUFSTFDUJPOʯWTʮϋϯυϥ͕ظ͢ΔҾͷ6OJPOʯ w ˠΤϥʔʂ
සग़ δΣωϦοΫͳҾͰDBMMCBDLΛݺͿ ͜Ε0WFSMPBEͳΒղܾग़དྷΔ͕ w "1*Πϕϯτ͕૿͑ͨΒͦͷશ෦0WFSMPBEॻ͘ʁˠݱ࣮త͡Όͳ͍ w ͔ͱ͍ͬͯઃܭͰಀ͛Δͷ͍͠ ͜͜ʹؔͯ͋͠ΔఔׂΓΔඞཁ͕͋Δͷ͔͠Εͳ͍
DPSSFMBUFEVOJPOTʹΑΔվળ VOJPOͷ݁ͼ͖ͭΛҡ࣋͢ΔΑ͏ͳਪͷվળঃʑʹͳ͞Ε͍ͯΔ w W*OEFYFE"DDFTT*OGFSFODF%FTUSVDUVSFE%JTDSJNJOBUFE6OJPO %FQFOEFOU1BSBNFUFST w WPCK<MJUFSBM,FZ>PCK<VOJRVFTZNCPM>ͷOBSSPXJOH w W$POTUBOU*OEFYFE"DDFTTOBSSPXJOH*OGFSSFE5ZQF1SFEJDBUFT w
WδΣωϦοΫผϢχΦϯͷOBSSPXJOH֦ு
ύλʔϯ̏·ͱΊ w σʔλͷ࡞ʹ͓͍ͯEVOJPOʹͰ͖ͳ͍ͷઃܭͷ w ରԠ͍ͤͨ͞ܕৗʹҰॹʹੜ͢Δ͜ͱΛΕͳ͍ w ޙͷ6OJPOͷਪͷϔϧύʔΨʔυͰղܾ͕͍͠ w ಛʹؔͷབྷΉͷɾϋϯυϥʔύλʔϯͳͲ͍͠ w
গͣͭ͠վળ͍ͯͬͯ͠ΔͷͰࠓޙʹظ
࣍ ϓϩμΫτͷʮྑ͘ͳ͍ܕʯΛ୳ͯ͠ΈΑ͏ සग़ྫɾ͍͠ྫͷհ ʮྑ͘ͳ͍ܕʯΛྨ͢Δ ݟ͔Βӡ༻
ྨͷ࣠Λߟ͑Δ ࠓճʮͲ͏ରࡦ͢Δ͔ʯΛͱʹҎԼͷ̎ͭͷ࣠Ͱߟ͑ͯΈΔ w ڥքͰى͖ͯΔͷ͔෦Ͱى͖ͯΔͷ͔ w ֎෦ͱͷڥքʹΑΔͷWT෦Ͱىͬͯ͜͠·ͬͯΔ͜ͱ w ҆શݍʹԡͤ͠Δ͔ w ܕΨʔυϔϧύʔͳͲͰ҆શݍʹԡͤ͠ΔWT͍͠
ࠓճհͨ͠ύλʔϯΛྨͯ͠ΈΔ ԡͤ͠Δ ԡͤ͠ͳ͍ ڥք༝དྷ ෦༝དྷ " ࣮͋·Γͳ͍ $ # w
%0.&WFOUDBUDI w จࣈྻˠ#SBOEFE w VOLOXPOͰͷBT w fi MUFSJODMVEFT wGSPN&OUSJFT w%JTDSJNJOBUFEVOJPOͷੜ w ҾʹԠͨ͡ฦΓਪ w δΣωϦοΫͳҾͱϋϯυϥʔ
ͦΕͧΕͷॲํᝦ "ڥք༝དྷºԡͤ͠Δ w ˠεΩʔϚ ;PE ΛؚΉܕΨʔυ͕ใΘΕΔ w ˠʮܕΨʔυΛॻ͚ΔॴͰॻ͘ʯΛνʔϜنʹ #෦ىҼºԡͤ͠Δ w
ˠνʔϜͰܕϔϧύʔɾܕΨʔυूΛ࣋ͭ w ˠઃܭूͱ%3:ͷτϨʔυΦϑݟۃΊΔඞཁ͋Γ
ͦΕͧΕͷॲํᝦ $෦ىҼºԡͤ͠ͳ͍ w ͋ΔఔఘΊΔ͔͠ͳ͍͕ w ˠہॴͰBT@ts-expect-error ཧ༝Λίϝϯτ w ˠ54ͷਐԽΛ͏ DPSSFMBUFEVOJPOT
ରࡦΘ͔͚ͬͨͲ Ͳ͏ͬͨΒؾ͚ͮΔʁ
ةͳ͍κʔϯͷΞϯςφΛݚ͗·͢ ࠓͦ͜ʮ͜͜ةͳͦ͏ʯͱ͍͏ײ֮େࣄ w ίʔυϨϏϡʔͰͷࢦఠ"*ͷࢦࣔ w νʔϜͷڭҭɾΦϯϘʔσΟϯά w ͕ࣗࡶͳBTJHOPSFΛॻ͖ͦ͏ͳ࣌ͷϒϨʔΩ w ͦͦઃܭ͔࣌Β54ʹ༏͍͠σʔλʹͳͬͯΔ͔
ˠઌճΓͰ͖Δ΄Ͳ҆શͳӡ༻ɾઃܭʹͭͳ͕Δ
ࠓճͷੳ͔ΒಘΒΕͨνΣοΫϦετ ͜ΕΒʹ֘͢ΔίʔυΛॻ͍ͯΔɾݟͨ߹ཁҙαΠϯ🚨 ☑︎ ֎෦ͱͷڥքΛލ͍Ͱ͍Δ͔ʁ ☑︎ ྻɾΦϒδΣΫτͷಈతมΛܦ༝͍ͯ͠Δ͔ʁ ☑︎ UZQFͱWBMVFΛผͷࣜͰΈཱ͍ͯͯͳ͍͔ ☑︎
͏ଆͷܕΛؔͰδΣωϦοΫͳܕ͔Β֬ఆͤ͞Α͏ͱͯ͠Δʁ ☑︎ ಉ͡ଥڠ͕܁Γฦ͞Ε͍ͯͳ͍͔ ˞ͪΖΜ͜Ε͕શͯͰͳ͍
࣍ ϓϩμΫτͷʮྑ͘ͳ͍ܕʯΛ୳ͯ͠ΈΑ͏ සग़ྫɾ͍͠ྫͷհ ʮྑ͘ͳ͍ܕʯΛྨ͢Δ ӡ༻
ͦ͏͍ͬͯ Ͳ͏ͬͯӡ༻͢Δʁ
ӡ༻ʹ͚ͯ MJOUͰنԽ͢Δ w CBOUTDPNNFOUSVMF @ts-expect-erroSͰίϝϯτΛڧ੍ ΨΠυϥΠϯʹ໌ه w ྫ 'PSN fi
FMEมGBDUPSZʹू͢Δ͜ͱ ఆظతͳ୨Է͠ w QSPEVDUJPOͷas@ts-ignoreΛʙͰ୨Է͠
JO"*$PEFJOH "*Կ͠ͳ͍ͱಉ͡ଥڠΛ࠶ੜ࢈͍͢͠ w ؾ͍ͮͨΒas@ts-ignore͕૿͑ͯΔͦΜͳܦݧ͋ΔͷͰʁ نͱͯ͠ॻ͍͓ͯ͘ͱྑ͍ w ࠓճͷΑ͏ͳνΣοΫϦετΛʮةͳ͍໘ʯͱͯ͠໌ࣔ w Մೳͳճආࡦɾվળ໌͓ࣔͯ͘͠ w
"*͕ଥڠ͢Δ࣌ཧ༝Λग़ྗͤ͞Δ
୨Է͠"*ʹͤ͞Α͏🤖 ࠓͷUBMLͷωλ"*ʹίʔυϕʔεΛੳͤͨ͞Ռ͔Βελʔτ ͱݴ͏͜ͱΈΜͳ؆୯ʹ࢝ΊΒΕΔʂ w "*ʹͤΔasɾ@ts-ignoreͷϦετΞοϓύλʔϯผͷࣗಈྨ w ਓؒ XJUI"* ͕அ54ͷݶք͔PSઃܭͷ͔༏ઌߴ͍͔ ˠු্ͨ͠ଥڠΛվળνέοτ🎫
࠶ܝ୳͠ํ ୳ͤ͞ํ ࠓͷ࣌"*͕͋ΔͷͰੵۃతʹ׆༻͠Α͏ʂ ҎԼΛूதͯ͠ཏతʹ୳ͤͨ͞ w @ts-ignore@ts-expect-error w BTΩϟετ as constas
unknown asΛআ֎ w ܕΨʔυؔvalue is X ͋Δఔࡉ͔͘ྨͤ͞Δˠྨ͝ͱʹ࣮ࢪʹίʔυΛݟͯஅ
·ͱΊ ۀͷʮྑ͘ͳ͍ܕʯʹύλʔϯ͕͋Δ w ͨ͘͞Μ͋ͬͯେύλʔϯʹऩ·Δ w ࠓճ ઃܭͷΈɺ54ͷදݱྗͷݶքͩͬͨ ͦΕͧΕͷύλʔϯΛੳ͢Δͱ w ઃܭͷ͍͠ͱ͜Ζ54ͷݶքɾ54ͷࠓ·Ͱͱ͜Ε͔ΒΛΕΔ
w νʔϜϝϯόʔ"*ͷྐʹͳΔ օ͞Μͥͻऩूɾੳͯ͠ΈΑ͏ʂ
࠷ޙʹ
͔ͤͬ͘ʮϦΞϧʯͷ ΧϯϑΝϨϯεʹ͍Δͷ͔ͩΒ
օ͞Μͷࢥ͍ݟฉ͖͍ͨ ͖ͬͱௌ͍ͯΔΈͳ͞Μ͍ΖΜͳ͜ͱΛࢥͬͯ͘Εͨͣ w ʮͦΕ࣮ͬͱ্ख͘ղܾ͢Δํ๏͋ͬͯʯ w ʮ54Ҏ֎ͷଞͷݴޠͩͱ͕ͯͨͭ͠͏·͍͘͘ΜͰ͢Αʯ w ʮҎલ͜ͷJTTVFͰͯͨ͠ͷͰղܾ͢Δ͔͠Ε·ͤΜΑʁʯ w ʮΑ͋͘ΔύλʔϯͰ͜͏͍͏ͷ͋Γ·ͤΜʁʯ
w ʮ͏ͪͰ͜Μͳӡ༻Ͱ͍Ͱ·͢Αʙʯ w FUD
એϒʔεʹ͍·͢ʂ ฐࣾαΠϘζ(PMEεϙϯαʔͱͯ͠ϒʔεΛग़͍ͯ͠·͢ʂ ͥͻ༡ͼʹ͖͍࣭ͯͩ͘͞ɾ͓8FMDPNFʂ
օ༷҆͝શʹʂ 3ZVTFJ4BKJLJ!TBKJLJY ܕ