為什么選擇使用 TypeScript ?
2020 年最有前途的五種語言,TypeScript 已經(jīng)成為其中之一。大約 60% 的前端程序員正在使用或曾使用過 TypeScript,而另外 22% 的開發(fā)者希望嘗試使用。那么什么是 TypeScript?
TypeScript 和 JavaScript 語法沒有明顯的區(qū)別,意味著你無需學(xué)習(xí)很多知識(shí)就可以開始無縫編寫 TypeScript 代碼。簡而言之,TypeScript 是 JavaScript 的超集。
所以你準(zhǔn)備好了嗎?如果沒有,那么接下來這篇文章幫你。感興趣的同學(xué)可以結(jié)合來自 Leslie/Jare 的官方系列教程 Cocos Creator 3.0 TypeScript 使用答疑一起食用~
)


—▼—
什么是 TypeScript


TypeScript 存在的意義
—▼—

) 
—▼—

TypeScript 帶來了什么改變
)TypeScript 的特點(diǎn)
類型系統(tǒng)
)let name: string = '陳皮皮';
name = 9527; // 報(bào)錯(cuò)
let age: any = 18;
age = 'eighteen'; // 不報(bào)錯(cuò)


// 枚舉
enum Direction {
Up = 1,
Down,
Left,
Right
}
let direction: Direction = Direction.Up;
// 元組
let x: [string, number];
x = ['hello', 10]; // 不報(bào)錯(cuò)
x = [10, 'hello']; // 報(bào)錯(cuò)

—▼—
修飾符和靜態(tài)關(guān)鍵字

class Me {
public name = '陳皮皮'; // 大家都知道我叫陳皮皮
private secret = '*******'; // 我的秘密只有我知道
protected password = '********'; // 我的支付寶密碼會(huì)告訴我的后人的
}
let me = new Me();
let a = me.name; // 拿到了我的名字
let b = me.secret; // 報(bào)錯(cuò),私有的屬性
let c = me.password; // 報(bào)錯(cuò),受保護(hù)的屬性
class Child extends Me {
constructor() {
super();
this.name = '陳XX';
this.secret // 報(bào)錯(cuò),無法訪問
this.password = '888888'; // 可以訪問
}
}
class Whatever {
public static origin: string = 'Whatever';
public static printOrigin() {
console.log(this.origin);
console.log(Whatever.origin);
};
}
console.log(Whatever.origin); // Whatever
Whatever.printOrigin(); // Whatever
abstract class Animal {
abstract eat(): void; // 不同動(dòng)物進(jìn)食的方式不一樣
}
let animal = new Animal(); // 報(bào)錯(cuò),法實(shí)例化抽象類無
class Dog implements Animal {
eat() {
console.log('我吃,汪!');
}
}
let dog = new Dog();
dog.eat(); // 我吃,汪!
class Cat implements Animal {
// 報(bào)錯(cuò)了,沒有實(shí)現(xiàn)進(jìn)食的功能
}
class Human {
name: string;
readonly id: number;
constructor(name: string, id: number) {
this.name = name;
this.id = id;
}
}
let human = new Human('陳皮皮', 666666);
human.name = '陳不皮'; // 名字可以改
human.id = 999999; // 報(bào)錯(cuò),身份證號(hào)碼一旦確定不能更改
—▼—
接口
// 擴(kuò)展 String 類型
interface String {
/**
* 翻譯
*/
translate(): string;
}
// 實(shí)現(xiàn)翻譯函數(shù)
String.prototype.translate = function () {
return this; // 不具體寫了,直接返回原字符串吧
};
// 使用
let nickname = '陳皮皮'.translate();
interface Human {
name: string; // 普通屬性,必須有但是可以改
readonly id: number; // 只讀屬性,一旦確定就不能更改
hair?: number; // 可選屬性,挺禿然的
}
let ChenPiPi: Human = {
name: '陳皮皮',
id: 123456789,
hair: 9999999999999
}
interface Vehicle {
wheel: number;
engine?: string;
run(): void;
}
class Car implements Vehicle {
wheel: 4;
engine: '帝皇引擎';
run() {
console.log('小汽車跑得快!')
}
}
class Bike implements Vehicle {
wheel: 2;
run() {
console.log('小黃車沖沖沖!')
}
}
—▼—
類型別名
// 給原始類型起個(gè)小名
type UserName = string;
let userName: UserName = '陳皮';
// 還可以是函數(shù)
type GetString = () => string;
let getString: GetString = () => {
return 'i am string';
}
let result = getString();
// 創(chuàng)建一個(gè)新的類型
type Name = {
realname: string;
nickname: string;
}
let name: Name = {
realname: '吳彥祖',
nickname: '陳皮皮'
}
// 再來一個(gè)新的類型
type Age = {
age: number;
}
// 用上面兩個(gè)類型擴(kuò)展出新的類型
type User = Name & Age;
let user: User = {
realname: '吳彥祖',
nickname: '陳皮皮',
age: 18,
}
—▼—
聯(lián)合類型
let bye: string | number;
bye = 886; // 不報(bào)錯(cuò)
bye = 'bye'; // 不報(bào)錯(cuò)
bye = false; // 報(bào)錯(cuò)
function padLeft(value: string, padding: string | number) {
if (typeof padding === 'string') {
return padding + value;
} else {
return Array(padding + 1).join('') + value;
}
}
padLeft('Hello world', 4); // 返回 ' Hello world'
padLeft('Hello', 'I said: '); // 返回 'I said: Hello'
—▼—
泛型
// 這是一個(gè)清洗物品的函數(shù)
function wash<T>(item: T): T {
// 假裝有清洗的邏輯...
return item;
}
class Dish { } // 這是盤子
let dish = new Dish(); // 來個(gè)盤子
// 盤子洗完還是盤子
// 用尖括號(hào)提前告訴它這是盤子
dish = wash<Dish>(dish);
class Car { } // 這是汽車
let car = new Car(); // 買輛汽車
// 汽車洗完還是汽車
// 沒告訴它這是汽車但是它認(rèn)出來了
car = wash(car);
// 盒子
class Box<T>{
item: T = null;
put(value: T) {
this.item = value;
}
get() {
return this.item;
}
}
let stringBox = new Box<String>(); // 買一個(gè)用來裝 String 的盒子
stringBox.put('你好!'); // 存一個(gè) '你好!'
// stringBox.put(666); // 報(bào)錯(cuò),只能存 String 類型的東西
let string = stringBox.get(); // 拿出來的是 String 類型
—▼—
裝飾器
export function color(color: string) {
return function (target: Function) {
target.prototype.color = color;
}
}
@color('white')
class Cloth {
color: string;
}
let cloth = new Cloth();
console.log(cloth.color); // white
@color('red')
class Car {
color: string;
}
let car = new Car();
console.log(car.color); // red
const { ccclass, property } = cc._decorator;
@ccclass
export default class CPP extends cc.Component {
@property(cc.Node)
private abc: cc.Node = null;
}
—▼—
命名空間
// pp 命名空間
namespace pp {
export class Action {
public static speak() {
cc.log('我是皮皮!');
}
}
}
// dd 命名空間
namespace dd {
export class Action {
public static speak() {
cc.log('我是弟弟!');
}
}
}
// 使用
pp.Action.speak(); // 我是皮皮!
dd.Action.speak(); // 我是弟弟!
namespace Lobby {
export interface Request {
event: string,
other: object
// ...
}
}
namespace Game {
export interface Request {
event: string,
status: string
// ...
}
}
// 用于 Lobby 的請(qǐng)求函數(shù)
function requestLobby(request: Lobby.Request) {
// ...
}
// 用于 Game 的請(qǐng)求函數(shù)
function requestGame(request: Game.Request) {
// ...
}
—▼—
聲明文件

Creator 中 TS 和 JS 在使用上的區(qū)別
聲明組件
const { ccclass } = cc._decorator;
@ccclass
export default class Test extends cc.Component {
}
cc.Class({
extends: cc.Component,
});
—▼—
聲明屬性
const { ccclass, property } = cc._decorator;
@ccclass
export default class Test extends cc.Component {
@property
myNumber: number = 666;
@property
myString: string = '666';
@property
myBoolean: boolean = true;
@property(cc.Node)
myNode: cc.Node = null;
@property([cc.Node])
myNodes: cc.Node[] = [];
@property({
visible: true,
displayName: '位置',
tooltip: '就是一個(gè)位置'
})
myVec2: cc.Vec2 = new cc.Vec2();
@property({
type: cc.Sprite,
visible() { return this.myBoolean },
tooltip: '當(dāng) myBoolean 為 true 才會(huì)展示該屬性'
})
mySprite: cc.Sprite = null;
@property
_getset = 0;
@property
get getset() { return this._getset }
set getset(value) { this._getset = value }
}
cc.Class({
extends: cc.Component,
properties: {
myNumber: 666,
myString: '666',
myBoolean: true,
myNode: cc.Node,
myNodes: [cc.Node],
myVec2: {
default: new cc.Vec2(),
visible: true,
displayName: '位置',
tooltip: '就是一個(gè)位置'
},
mySprite: {
type: cc.Sprite,
default: null,
visible() { return this.myBoolean },
tooltip: '當(dāng) myBoolean 為 true 才會(huì)展示該屬性'
},
_getset: 0,
getset: {
get() { return this._getset; },
set(value) { this._getset = value; }
}
}
});
—▼—
導(dǎo)入/導(dǎo)出組件/模塊
// A.ts
const { ccclass, property } = cc._decorator;
@ccclass
export default class A extends cc.Component {
@property
public nickname: string = 'A';
public greet() {
cc.log('A: greet()');
}
}
// B.ts
import A from "./A";
const { ccclass, property } = cc._decorator;
@ccclass
export default class B extends cc.Component {
@property(A)
private a: A = null;
onLoad() {
// 訪問實(shí)例屬性
let nickname = this.a.nickname;
// 調(diào)用實(shí)例函數(shù)
this.a.greet();
}
}
// A.js
let A = cc.Class({
extends: cc.Component,
properties: {
nickname: 'A'
},
greet() {
cc.log('A: greet()');
}
});
module.export = A;
// B.js
let A = require('./A');
let B = cc.Class({
extends: cc.Component,
properties: {
a: {
type: A,
default: null
}
},
onLoad() {
// 訪問實(shí)例屬性
let nickname = this.a.nickname;
// 調(diào)用實(shí)例函數(shù)
this.a.greet();
}
});
module.export = B;
—▼—
靜態(tài)變量/函數(shù)
// A.ts
const { ccclass, property } = cc._decorator;
@ccclass
export default class A extends cc.Component {
public static id: number = 999999;
public static staticGreet() {
cc.log('A: staticGreet()');
}
}
// B.ts
import A from "./A";
const { ccclass, property } = cc._decorator;
@ccclass
export default class B extends cc.Component {
onLoad() {
// 訪問靜態(tài)屬性
let id = A.id;
// 調(diào)用靜態(tài)函數(shù)
A.staticGreet();
}
}
// A.js
let A = cc.Class({
extends: cc.Component,
static: {
id: 999999,
staticGreet() {
cc.log('A: staticGreet()');
}
}
});
module.export = A;
// B.js
let A = require('./A');
let B = cc.Class({
extends: cc.Component,
onLoad() {
// 訪問靜態(tài)變量
let id = A.id;
// 調(diào)用靜態(tài)函數(shù)
A.staticGreet();
}
});
module.export = B;
—▼—
枚舉
// TypeScript 腳本的方式
enum Direction {
Up = 1,
Down,
Left,
Right
}
// JavaScript 腳本的方式
const Direction = cc.Enum({
Up = 1,
Down,
Left,
Right
});
如何創(chuàng)建 Creator TS 項(xiàng)目

原有的 JS 項(xiàng)目使用 TS
creator.d.ts 是 Cocos Creator 引擎 API 的聲明文件
tsconfig.json 是 TypeScript 項(xiàng)目的環(huán)境配置文件


往期精彩
評(píng)論
圖片
表情



