每天資訊Cocos Creator 3.0 TypeScript 使用答疑

菜單

Cocos Creator 3.0 TypeScript 使用答疑

去年年底大家已經沉浸在吃瓜和放假前夕的放鬆氛圍時,很長一段時間我們都在加班加點,終於趕在年前讓灌注了汗水與熱血的

Cocos Creator 3.0

來到了大家面前。

3。0

合併了原有 2D 和 3D 兩套產品的所有功能

,不僅延續了 Cocos 在 2D 品類上輕量高效的優勢,並且為 3D 重度遊戲提供高效的開發體驗。

我們很高興看到 3。0 在釋出後引發了熱烈的討論,也收到許多同學的反饋,這當中也包括了許多不一樣的聲音,有人覺得我們想太多,也有人覺得我們想太少,等等等等。

我們也知道大家都希望我們第一個版本就非常完美、沒有 bug,我們呢當然是希望大家不要有這種希望,開玩笑開玩笑哈哈哈。

其實社群的帖子我們都有看到,始終非常感謝大家一直以來的默默支援,和耐心等待。這次我們也

集結引擎組所有功能開發的一線大佬,開闢《Cocos Creator 3.0 技術專欄》

,希望能幫助大家絲滑升級,減少開發阻礙。

我們也會在 3。0 的基礎上繼續深耕,用心踏踏實實完善產品體驗,普惠所有開發者。希望大家可以感受到我們真誠的態度和敬業的精神,放心地給 3。0 一個機會。

本篇為專欄第一篇文章,作者

Leslie+Jare

,希望能給大家帶來幫助,歡迎閱讀。

雖然 Creator 很早就支援了 TypeScript,直到 3。0 我們才正式廢棄了對 JavaScript 的支援。但隨著這次 3。0 的全面升級,很多第一次使用 TypeScript 的開發者仍然遇到了不少阻礙。

本文將對這次調整做一次簡要回顧,並且

解答開發者在語言升級的過程中容易遇到的一些問題

我們在 TS 上的鋪墊

我們對 TypeScript 的支援由來已久,最早可追溯到 17 年 5 月釋出的 v1。5。0,此後我們一直在聽取 TS 開發者的反饋,逐步完善 TS 的支援。

在 18 年的時候,3D 專案組開始用 TS 重寫整個 3D 引擎和編輯器,驗證了 TS 處理超大規模專案時的能力,讓我們對 TS 有了更大的信心和第一手的使用經驗。

到了 19 年,我們在 Cocos Creator 3D 正式釋出時,第一次正式廢棄了對 JavaScript 的支援,而後持續聽取開發者們對這一改變的反饋。

要採用哪一門語言做為引擎的開發語言,不是一個能輕易做出的決定

,對開發者、對生態都影響巨大。

Cocos Creator 當初選擇 JS 時,已經歷過一次飽受非議,這次如果不是有前面幾年在 TS 上的鋪墊,我們也沒有勇氣在 3。0 做出這個關鍵調整。

為什麼要轉向 TS

在 Cocos Creator 14 年剛立項之初,由於熟悉的語法,TypeScript 成為了我們入門 JavaScript 的良好橋樑。但由於當時的 TS 剛剛正式釋出,生態仍未成熟,因此我們只能先使用最原生的 JavaScript。

經過了這麼多年的發展,今天

TS 已經成為一門非常成熟的語言,有豐富的生態和群眾基礎,可以勝任任何型別的遊戲開發需要

從我這幾年跟研發團隊的接觸來看,大多數團隊都逃不過 TS 的真香定律,網上也有大量對 TS 的安利文章,我就不再贅述 TS 的優勢,直接從我們的角度分享下,我們是怎麼想的。

我們始終相信,

良好的程式語言是專案成功的基石

誠然,任何語言和框架都只是工具,優秀的程式設計師不論用什麼工具都能把專案做好。不過良好的語言更能降低專案整體風險,讓開發人員心情愉悅,提升協作效率,從長遠來看更能降低整個團隊的研發成本!

我們堅信,

Cocos Creator 不僅僅是一個小遊戲引擎,它必定要能支撐大型重度遊戲的開發。

JavaScript 或許能滿足高手自己做一些小專案的需要,能快速做點小東西玩玩,但是達不到大型專案的工業標準。

我們意識到,JavaScript 做為弱型別語言,遲早會成為 Cocos Creator 專案的最佳化瓶頸,只有強型別語言才有機會徹底提升整個專案的效能表現。

所以我們持續在探索 JavaScript 編譯為原生語言的可能性,這離不開 TypeScript 的支援。

今天已經有 AssemblyScript 這樣成熟的專案支援將 TypeScript 方言編譯為 WebAssembly,事實上同類項目還有很多。

只有從生態、社群的角度統一大家的開發語言,將來我們才有機會為大家送上這份大禮。

語言的割裂會阻礙生態的發展

今天在 Cocos Creator 社群已經擁有了一幫 TypeScript 的簇擁,很多優質的教程、外掛、帖子都使用 TypeScript 釋出。如果官方文件、官方案例都使用一門語言編寫,將不利於另一門語言的學習。

如果社群長期擁有兩門語言,更不利於大家複用前人的工作成果。JavaScript 開發者無法適應 TypeScript 專案的維護,TypeScript 開發者在複用原有的 JavaScript 元件時也會遇到阻礙。

常見的 TypeScript 認知誤區

誤區:

Cocos Creator 僅支援 TypeScript,不支援 JavaScript

TypeScript 是 JavaScript 的超集並且 TypeScript 緊緊依賴 JavaScript。Cocos Creator 3。0 仍支援 TypeScript 和 JavaScript 並用。

然而,Cocos Creator 鼓勵使用者使用 TypeScript 以獲得更好的開發體驗,提高開發質量,因此在編輯器中僅支援建立 TypeScript 指令碼。

如果你確定一定要使用 JavaScript,以其他方式(資源管理器、訪達等)建立 JavaScript 檔案仍然是允許的。

誤區:

import/export 是 TypeScript 專有的,我無法在 JavaScript 中使用

require

import/export 是 JavaScript 規範 ECMAScript 2015 引入的對模組支援的語法,因此 JavaScript 中是可以使用的,並不是 TypeScript 專有。

另一方面,require/exports/module 是 CommonJS 模組系統中的變數。它們不屬於 JavaScript 標準。

儘管,在 3。0 中提供了對 CommonJS 模組的有限支援

將 JavaScript 程式碼

遷移為 TypeScript

上述有提到 JavaScript 可以直接使用。但只要瞭解 TypeScript 的用法,將 JavaScript 程式碼遷移為 TypeScript 也是一件輕鬆的事。

最簡單的遷移:改字尾名

可以直接將 。js 檔案重新命名為 。ts 完成最簡單的遷移——只要 JavaScript 在執行時沒問題,那麼如此改為 TypeScript 也一定是沒問題的。

改名後,在 IDE 中會有一大堆報錯,這是因為缺少型別資訊。如果你暫時不想解決這些型別問題,大可以在整個檔案的頭部加一句註釋:

來跳過對該檔案的型別檢查。

在程式碼中補充型別資訊

對於比較簡單的 JavaScript 程式碼,只要稍加補充一些型別資訊就可以。例如:

為 fn 指定引數型別就 OK:

TypeScript 會自動根據函式體內的程式碼推斷出函式的返回值。你當然也可以顯式指定:

在程式碼外部宣告型別資訊

有些時候,JavaScript 程式碼不是我們自己寫的,而是由第三方提供的庫程式碼。這時候我們可以在不編輯它的情況下為它補充型別資訊。

例如,有一個第三方的 JavaScript 檔案 foo。js:

我們可以在同目錄下建立一個同名但副檔名為 。d。ts 的 foo。d。ts:

嚴格模式:“null” 問題

從 JavaScript 轉入 TypeScript 的同學可能被一些“型別問題”所困擾。

看這樣一個問題:

這段程式碼在 IDE 中會報錯,報錯源頭是屬性 material 的宣告。

有一種情況是,material 屬性僅在初始化時是空值,但是後續任何時候訪問都是有值的。例如,給該屬性附加 @property 裝飾器時,就可以在編輯器中編輯該欄位,拖拖拉拉之後由 Creator 幫我們賦值該欄位。

那我們如何向 TypeScript 傳達這種資訊呢?

我們來分析一下報錯的原因,material: Material 將 material 欄位宣告為 Material 型別,這個意思就是在任何時候拿到 material 它都是 Material 型別。

初始化式 = null 告訴它將 material 初始化為 空值 null,與上條說法違背。

這便是,TypeScript 的嚴格型別檢查。它要求你將型別對上號。TypeScript 編輯器是預設開啟該選項的,Creator 也不例外。

既然知道了出錯原因,那麼我們就可以有以下幾種思路去解決。

正確描述它的型別為:既可能是 Material,也可能是 null

向 TypeScript 型別系統表達:我只是初始化為 null,後續使用時候其實都是 Material

關閉 TypeScript 對空值的檢查。

可空型別

我們可以將 material 的型別描述為既可能是 Material,也可能是 null:

這樣初始化為 null 就順理成章了。

然而,這樣的缺陷是當你後續訪問 material 時,TypeScript 要求你處理空值的情況。例如:

TypeScript 型別系統會提示你:this。material 可能是空值 null,無法訪問 null 的屬性。

但是,只要 TypeScript 在此處知道它一定是不為空的,它就會收起這條錯誤:

因為你做了判斷,當執行到 if 語句塊內的時候,this。material 一定是不為空的,因此可以訪問 name 屬性。

表示式非空斷言

每次使用的時候都要用 if 語句判斷一下實在有些繁瑣,況且 if 語句在執行時是會去執行的。

如果你一定能確保“在執行到這裡的時候 this。material 一定非空”,那麼我們可以用TypeScript 非空斷言語法來表達:

感嘆號 ! 稱作 非空斷言運算子,它斷言前面的表示式是非空的。

注意此感嘆號是 TypeScript 特有的,僅為型別目的;編譯後,會直接移除。

我們還可在初始化時就作此斷言:

還一個經常用於非空斷言的地方是 Node。getComponent(),此方法返回的是可能為空的元件。如果能確保元件一定存在,則可以透過非空斷言來避免 if 判斷。

顯式賦值斷言

在標準的 JavaScript 語法裡,是可以不給初始化式的,這樣的欄位將被初始化為 undefined:

在 TypeScript 裡也允許這麼做,不過你得提示一下 TypeScript,以讓它跳過這裡的型別檢查:

屬性名後的感嘆號稱為 顯式賦值斷言(Definite Assignment Assertion),它告訴 TypeScript 此欄位在別處初始化。

OK,這裡你將得到一個雖然宣告為 Material,但是初始化為 undefined 的欄位。

禁用空值檢查

當然了,如果你是非常不喜歡 TypeScript 的型別系統,你更喜歡所有事靠自己確保,那麼你可以關閉嚴格型別檢測。在 /tsconfig。json 裡,加上選項:

需要提醒的是,我們並不鼓勵這種做法,因為嚴格空值檢查能夠減少 JS 程式碼執行時的一些低階報錯。放一張最近我們收到的使用者反饋做為旁證:

Cocos Creator 3.0 TypeScript 使用答疑

總結

以上就是此次跟大家介紹的全部內容。感謝大家在論壇裡將遇到的實際問題與我們反饋交流,才讓我們一路以來越來越好。

過去一年我們助力開發者創作出了許多

精彩遊戲

,未來我們仍會在 3。0 的基礎上大力深耕,突破引擎技術的天花板,普惠廣大開發者。大家可以放心給 3。0 一個機會,

多多使用 3.0 用於實際專案製作

後續本專欄將不定期更新,為大家帶來包括但不限於以下內容:

《Cocos Creator 3。0 裡如何玩轉 npm 海量資源》by 放空

《深入Cocos Creator 3。0 的外掛擴充套件系統》by sijie

《Cocos Creator 3。0 的 3D 物理講解》by Jayce Lai

《Cocos Creator 3。0 的資源系統》by Santy Wang

……

讓我們在此先隆重感謝各位作者,並以此道德綁架他們,希望他們儘快交稿哈哈哈。

如果大家有關於 3。0其他

想看的內容

或是

使用上的問題

,或是

其他想說的

,歡迎在評論處留言告訴我們。

我們將在本週五(3月5日)為評論區

點贊最高的同學送出 Cocos 周邊大禮包

,並

隨機抽出 5 位童靴隨機送出周邊

,希望能聽到更多大家的聲音,也歡迎大家將本文轉給有需要的同學。

Cocos Creator 3.0 TypeScript 使用答疑

最後,再次感謝大家一路陪我們到這裡,一起去到更遠的地方吧。