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