聲明))
【聲明】本博客所有內(nèi)容均為個(gè)人業(yè)余時(shí)間創(chuàng)作所述技術(shù)案例均來自公開開源項(xiàng)目如GithubApache基金會不涉及任何企業(yè)機(jī)密或未公開技術(shù)如有侵權(quán)請聯(lián)系刪除標(biāo)題160、【Agent】【OpenCode】TuiThreadCmd箭頭函數(shù)聲明背景上篇 blog【Agent】【OpenCode】TuiThreadCmd代理 Fetch分析了代理 Fetch 函數(shù)其返回值的類型是typeof fetch意味著這個(gè)函數(shù)的聲明與原生fetch完全兼容可以直接替換全局fetch使用原生fetch是瀏覽器和現(xiàn)代 Node.js/Bun 運(yùn)行時(shí)內(nèi)置的全局函數(shù)用來發(fā) HTTP 請求它既是一個(gè)具體的函數(shù)實(shí)現(xiàn)也代表了一種函數(shù)類型/接口契約并強(qiáng)調(diào)了在 TypeScript 中函數(shù)的類型本身就是一種合法的類型最后總結(jié)了typeof fetch就是原生 fetch 函數(shù)的類型聲明下面繼續(xù)分析OpenCode還是這行函數(shù)定義之前提到了原生fetch函數(shù)定義下面拆開看這個(gè)函數(shù)類型定義語法typeFetchType(input:RequestInfo|URL,init?:RequestInit)PromiseResponse這里是 TypeScript 中定義函數(shù)類型的標(biāo)準(zhǔn)寫法。下面把它拆成 3 個(gè)部分來理解1.|是什么聯(lián)合類型|在 TypeScript 里叫 Union Type聯(lián)合類型意思是“或者”。RequestInfo | URL這個(gè)參數(shù)可以是RequestInfo或者是URL就像去餐廳點(diǎn)餐可以選牛排|意面二選一都行所以input: RequestInfo | URL的意思是第一個(gè)參數(shù)名叫 input它既接受一個(gè)RequestInfo對象也接受一個(gè)URL對象。這正好對應(yīng)了原生fetch的用法// ? 傳字符串屬于 RequestInfofetch(https://example.com)// ? 傳 URL 對象fetch(newURL(https://example.com))// ? 傳 Request 對象也屬于 RequestInfofetch(newRequest(https://example.com))2. 整個(gè)函數(shù)類型怎么解析把(input: RequestInfo | URL, init?: RequestInit) PromiseResponse從左到右翻譯一下語法片段含義( ... )這是一個(gè)函數(shù)的參數(shù)列表input: RequestInfo | URL第1個(gè)參數(shù)叫 input類型是 RequestInfo 或 URLinit?: RequestInit第2個(gè)參數(shù)叫 init?表示可選類型是 RequestInit箭頭左邊是參數(shù)右邊是返回值這是函數(shù)類型的固定語法PromiseResponse這個(gè)函數(shù)返回一個(gè) Promiseresolve 后得到 Response 對象??注意區(qū)分兩種箭頭用在類型定義中分隔參數(shù)和返回值(a: string) number用在實(shí)際函數(shù)實(shí)現(xiàn)中是箭頭函數(shù)語法const fn (a: string) 42它們長得一樣但語境完全不同。下面詳細(xì)分析下這兩個(gè)的區(qū)別的這兩種用法在編譯器眼里和運(yùn)行時(shí)結(jié)果上是兩個(gè)完全不同的東西。核心區(qū)別只有一句話類型定義里的是描述形狀編譯后消失實(shí)現(xiàn)里的是創(chuàng)建函數(shù)編譯后變成真代碼。下面從三個(gè)維度來拆解1. 編譯后的產(chǎn)物最本質(zhì)的區(qū)別代碼編譯后的 JS運(yùn)行時(shí)存在嗎t(yī)ype Fn (a: string) number空? 完全消失不占任何字節(jié)const fn (a: string) 42const fn (a) 42;? 真實(shí)存在的函數(shù)對象類型里的只是給 TS 編譯器看的注釋。編譯完成后這一整行都被擦除了JS 引擎根本不知道它的存在。實(shí)現(xiàn)里的是 ECMAScript 標(biāo)準(zhǔn)的箭頭函數(shù)語法。編譯后依然保留會在內(nèi)存中創(chuàng)建一個(gè)真正的函數(shù)對象。2. 能放在哪里語法位置不同// ? 類型 只能出現(xiàn)在類型上下文中typeA(x:string)number// 類型別名interfaceB{fn:(x:string)number}// 接口屬性functioncall(cb:(x:string)number){}// 參數(shù)類型// ? 實(shí)現(xiàn) 只能出現(xiàn)在值/表達(dá)式上下文中consta(x:string)42// 變量賦值constb[(x:string)42]// 數(shù)組元素call((x:string)42)// 傳參// ? 不能互換typeC(x:string){return42}// 報(bào)錯(cuò)類型里不能有函數(shù)體constd:(x:string)number// 報(bào)錯(cuò)變量聲明缺少賦值3. 箭頭的右邊是什么這是肉眼區(qū)分的最快方法類型右邊一定是一個(gè)類型名→number, string, PromiseResponse, void實(shí)現(xiàn)右邊一定是一個(gè)表達(dá)式/語句塊→42, hello, { return x 1 }, await fetch()// 類型右邊是類型typeT(a:string)PromiseResponse// ^^^^^^^^^^^^^^^^ 這是一個(gè)類型// 實(shí)現(xiàn)右邊是表達(dá)式constf(a:string)newResponse()// ^^^^^^^^^^^^^^ 這是一個(gè)構(gòu)造表達(dá)式為什么 TS 要這么設(shè)計(jì)就是為了讓“描述”和“實(shí)現(xiàn)”看起來像同一種語言。當(dāng)寫constmyFetch:typeoffetchasync(input,init?){...}// ^^^^^^^^^^^^^^^^ 類型描述用 // ^^^^^^^^^^^^^^^^^^^^ 實(shí)際實(shí)現(xiàn)也用 左右兩邊視覺上對稱讀起來就像在說聲明了一個(gè)符合fetch形狀的函數(shù)然后真的實(shí)現(xiàn)了它。如果類型語法改成(a: string) - number這種不一樣的符號反而會增加認(rèn)知割裂感。一句話記憶看到先思考這行代碼刪掉后程序還能跑嗎刪了還能跑 →類型純描述刪了就報(bào)錯(cuò) →實(shí)現(xiàn)真代碼OK本篇先到這里如有疑問歡迎評論區(qū)留言討論祝各位功力大漲技術(shù)更上一層樓更多內(nèi)容見下篇 blog