让前端的子弹飞-TypeScript

4,845 阅读6分钟
Any application that can be written in JavaScript,will eventually be written in JavaScript.

-- Jeff Atwood 2007

前端,文也;
后端,武也;
全栈,文武双全者也;
前端全栈者,涉猎甚广,
文可交互,武可并发,
硬件编程,更添异彩。
吾乃前端门下后生之辈,时值太学二年,拜入星辰门下,
研修前端之术,数年以来,前端招式变化之快,
群雄割据,框架纷争,
三国鼎立者,Angular、React、Vue,吾惶恐不及,
09年始,NodeJS中途岛登陆,攻城略地,
超炫3D,WebVR,叹为观止。
古人有云,习前端者,足以立天下。

-- cuitianze 2016



本文开篇同时引用了编程界大牛和菜鸟的语录来"大肆"宣扬前端的地位,不,不止于前端,我们的真正名字应该叫JavaScript开发者,“前端”是历史遗留下的误解,亦或是在工作岗位中被局限于的小小领域。


01

Jeff Atwood定律


那么2007年提出震惊中外的“Atwood定律”的Jeff Atwood何许人也?他便是叱咤编程界的StackOverflow创始人。


原博客链接如下:https://blog.codinghorror.com/the-principle-of-least-power/。


Jeff Atwood定律的由来:JavaScript既能独立完成所有互联网应用所需的功能开发,同时又是主流编程语言中最为轻量级的。


02


JavaScript应用场景


JavaScript虽然不是万能的,但他却能运行在我们所期望能运行的任何地方,譬如:


  • 你的浏览器上(几乎所有的浏览器,估计不支持的浏览器早已消逝在历史长河中);

  • 你的手机和平板电脑(如React Native,Weex,Cordova);

  • 你的桌面应用(如Electron、NW.js可以横跨Mac、Windows、Linux三大主流操作系统);

  • 你的服务器上运行着NodeJS甚至最近刚推出的让人学不动了的Deno。


不仅如此,目前最高流量入口的微信小程序和支付宝小程序的开发语言全都是JavaScript,硬件编程语言中JavaScript也占得了一席之地,区块链应用开发中JavaScript也是不可或缺的一环。



03


JavaScript弊端


然而,尽管JavaScript如此火,几乎扛下了互联网应用的半壁江山,但在语言设计上却饱受诟病,正如Node 之父 Ryan Dahl所说的Node设计缺陷一样,其中也涉及到了JavaScript的短板,要不然他也不会在新服务端框架Deno中使用TypeScript作为主要语言。


冥冥中自有定数,Deno也许未必能替代Node,尤其是在Node已经诞生10年,早已是前端工程化中流砥柱的工具,全世界也有无数个运行中的服务端应用;而Deno此时此刻却仍然是Demo。但TypeScript必将从此一振,此时此刻,也许不是学习Deno的最佳时机,但一定是学习TypeScript的最佳时机。JavaScript开发者必将迎来一个崭新的时代,开启构建大型应用的新时代。


04


踩过的坑


曾几何时,我们在开发调试过程中不知道踩过了多少坑,无数次激昂澎湃地面对项目代码重构却望而却步,因为你不确定弱类型的JavaScript代码究竟埋藏了多少地雷,也许正是你亲手埋下的。


JavaScript的函数可以接受任意类型的参数,看起来很灵活,但一不小心就让我们陷入排查Bug的地狱中。


function func(anything) {
    return;
}


像Java这样的强类型语言,如果参数不是特定的类型就会报错,虽然在定义变量时有些繁琐,但确实能够在很大程度上避免很多低级却很隐蔽的Bug。


05


TypeScript的问世


鉴于以上问题,TypeScript横空出世,TypeScript是JavaScript的超集,遵循最新的ES6规范,弥补了JavaScript在大型应用开发中的不足。TypeScript在静态类型检查、代码重构和语言服务方面的优势十分明显,而这些正好是JavaScript的劣势。


除此之外,在前端面试过程中经常会考一些JavaScript类型转换的黑魔法,如+String类型可以转换成Number类型。我个人认为就算这样代码十分精简,也是不应该提倡使用的,因为这以牺牲代码可读性和可维护性为代价,让许久之后的重构变得有心无力、如履薄冰。


以弱类型语言著称的JavaScript在字符串、数字和日期等类型直接的隐式类型转换让流入和流出函数的对象类型变得无法窥视,导致在团队开发过程中,强调撰写代码注释成为家常便饭的事情,对代码进行注释变得极其重要,否则团队新成员很难立即接手项目。


TypeScript可以很好地解决这个问题,你不需要再单独提交一份文档进行详细地解释代码,TypeScript可以清楚地记录每一个对象的属性、方法的参数等。


06


TypeScript基本介绍


TypeScript支持与JavaScript几乎相同的数据类型,此外还提供了实用的枚举类型方便我们使用。

  • 布尔值

let isDone: boolean = false;

  • 数字

let decLiteral: number = 6;

  • 字符串

let name: string = "bob";

  • 数组

let list: number[] = [1, 2, 3];

  • 元组 Tuple

let x: [string, number];

  • 枚举

enum Color {Red, Green, Blue}

  • 任意值

let notSure: any = 4;

  • 空值

function warnUser(): void {

alert("This is my warning message");

}

let unusable: void = undefined;

  • Null 和 Undefined

let u: undefined = undefined;

let n: null = null;

  • Never

function infiniteLoop(): never {

while (true) {

}

}

  • Object

declare function create(o: object | null): void;


联合类型,又可以称之为选择类型,只要满足其一便可。


let age: number | string;


类,类是TS的核心,使用TS开发时,大部分代码都是写在类里面的。


class Greeter {
    greeting: string;
    constructor(message: string) {
        this.greeting = message;
    }
    greet() {
        return "Hello, " + this.greeting;
    }
}


更进一步,类有公共,私有与受保护的修饰符。


class Person {
    public name: string;
    private age: number;
    public constructor(theName: string) { this.name = theName; }
    protected move(distanceInMeters: number) {
        console.log(`${this.name} moved ${distanceInMeters}m.`);
    }
}


  • public 公有 任何人可以访问

  • private 私有 只有类内部可以访问

  • protected 受保护 只有子类能用


接口Interface,接口的作用就是为这些类型命名和为你的代码或第三方代码定义契约。


interface SquareConfig {
    color?: string;
    width?: number;
}

function createSquare(config: SquareConfig): {color: string; area: number} {
    let newSquare = {color: "white", area: 100};
    if (config.color) {
        newSquare.color = config.color;
    }
    if (config.width) {
        newSquare.area = config.width * config.width;
    }
    return newSquare;
}

let mySquare = createSquare({color: "black"});


其中“?”表示可选参数。


function test(a:string, b?:string, c:"ctz"){
    console.log(a);
    console.log(b);
    console.log(c);
}


泛型,在像C#和Java这样的语言中,可以使用泛型来创建可重用的组件,一个组件可以支持多种类型的数据。 这样用户就可以自定义数据类型来使用组件。


function identity<T>(arg: T): T {
    return arg;
}

let myIdentity: <T>(arg: T) => T = identity;


class Calc<T> {
    a: T;
    b: T;
}


07


TypeScript的未来


总之,对于Javascript来说,TypeScript就像超时代的自己!

随着技术的发展,JavaScript终会向着TypeScript的方向看齐,届时我们能更加游刃有余地开发超大型应用。

在未来,我相信,任何能用JavaScript实现的应用,终将使用TypeScript写成。

Any application that can be written in JavaScript,will eventually be written in TypeScript.


本文只是抛砖引玉,更多关于TypeScript的用法还需要大家在实践中自己去探索和慢慢积累。

TypeScript官方文档地址:http://www.typescriptlang.org/docs/home.html。


本文作者:黑马大前端 cuitianze