TypeScript是JavaScript的超集,带来了诸多新特性:
类型可被添加到变量,函数,属性等。这将帮助编译器在App运行之前就能显示出任何潜在的代码警告。
给JavaScript加上可选的类型系统,很多事情是只有静态类型才能做的,给JavaScript加上静态类型后,就能将调试从运行期提前到编码期,诸如类型检查、越界检查这样的功能才能真正发挥作用。TypeScript的开发体验远远超过以往纯JavaScript的开发体验,无需运行程序即可修复潜在bug。
在TypeScript中,你可以直接使用ES6的最新特性,在编译时它会自动编译到ES3或ES5。
参考:《 TypeScript的全部资料,以后都放这儿了》
var type = 1;
type = 'abc';
var obj = {a: 123, b: 323};
console.log(obj.c);
ajax('url', function (json){
json.result ??
}
框架:Angular 工具:TSLint 编辑器:VSCode 工具库:RxJS、UI-ROUTER UI:ANT Design React UI库 APP:Reddit
1. TypeScript 拥有很好的工具。
它提供了先进的自动补全功能,导航,以及重构。有这样的工具几乎是开发大型项目的必要条件。没了这些工具,修改代码的恐惧将会导致该代码库在一个半只读(semi-read-only)状态, 并且使大规模重构变得极具风险,同时消耗巨大资金。
2. TypeScript 使抽象概念明确。
一个好的设计在于定义良好的接口。支持接口的语言使得表达想法变得更加容易。 不能清楚地看到界限,开发者开始依赖具体类型而不是抽象接口,导致了紧密耦合。
3. TypeScript 使代码更易阅读和理解。
Typescript vs Flow:
Typescript是JavaScript的强类型版本。 Flow是通过一组可以添加到JavaScript的注解,然后通过工具检查正确性。 Flow的类型注解能自动的被Babel移除。 与TypeScript相比,Flow在类型检查中做得更好。 Typescript是强类型,能使代码有更少的类型相关bug,更容易构建大型应用,还有着丰富的生态系统。
TypeScript的一大加分项就是其生态系统,TypeScript的支持库实在是太棒了。
并且还支持目前流行的编辑器,比如VSCode, Atom和Sublime Text。
此外,TypeScript还支持解析JSDoc。
1. 提供了先进的自动补全功能,导航,以及重构工具。
构建丰富的开发工具从第一天起就成为了TypeScript团队的明确目标。 这也是为什么他们构建了编程语言服务,使得编辑器可以提供类型检查以及自动补全的功能。那么多的编辑器都对TypeScript有极好的支持,就是因为TypeScript提供了编程语言服务。
2. 是JavaScript的超集,从JavaScript迁移方。
从JavaScript迁移到TypeScript不需要经过大改写。可以慢慢的、一次一个模块的迁移。
随便挑选一个模块,修改文件扩展名.js为.ts,然后逐步添加类型注释。当你完成了这个模块,再选择下一个。 一旦整个代码库都被类型化,你就可以开始调整编译器设置,使其对代码的检查更加严格。
3. 支持接口,抽象设计。
在一个静态类型的编程语言中,使用接口来定义子系统之间的界限。
4. 类型的支持,使代码更易阅读和理解。
我们不需要深入了解代码的实现,也不需要去阅读文档,就可以更更好地理解代码。
5. 生态系统完善,支持库完备,已有不少使用TypeScript的成熟项目。
关于Typescript的语法,更多的可参考官方文档,这里只列出常用的:基础类型、接口和类。
TypeScript支持与JavaScript几乎相同的数据类型,此外还提供了实用的枚举类型使用。
// 布尔值
let isDone: boolean = false;
// 数字
let decLiteral: number = 6;
// 字符串
let name: string = "bob";
// 数组常用
// 在元素类型后面接上 []
let list: number[] = [1, 2, 3];
// 数组泛型,Array<元素类型>
let list: Array<number> = [1, 2, 3];
// any类型常用于对现有代码进行改写
let notSure: any = 4;
notSure = "maybe a string instead";
notSure = false;
// void类型像是与any类型相反,它表示没有任何类型
// 函数没有返回值
function warnUser(): void {
alert("This is my warning message");
}
// 默认情况下null和undefined是所有类型的子类型
// 可以把null和undefined赋值给各种类型的变量
let u: undefined = undefined;
let n: null = null;
TypeScript的核心原则之一是对值所具有的结构进行类型检查。 它有时被称做“鸭式辨型法”或“结构性子类型化”。
在TypeScript里,接口的作用就是为这些类型命名和为你的代码或第三方代码定义契约。
interface SquareConfig {
color: string;
// 可选属性
width?: number;
// 指定属性
type: 1 | 2 | 3;
// 只读属性
readonly x: number;
// 函数类型
getArea(x: number): number;
}
接口继承
interface Shape {
color: string;
}
// 接口继承
// 此时Square同时具有两个属性
interface Square extends Shape {
sideLength: number;
}
ECMAScript 6开始,JavaScript程序员将能够使用基于类的面向对象的方式。
class Greeter {
greeting: string;
constructor(message: string) {
this.greeting = message;
}
greet() {
return "Hello, " + this.greeting;
}
}
let greeter = new Greeter("world");
当接口继承了一个类类型时,它会继承类的成员但不包括其实现。 接口同样会继承到类的private和protected成员。
公共,私有与受保护的修饰符:
class Person {
protected name: string;
constructor(name: string) { this.name = name; }
}
class Employee extends Person {
private department: string;
constructor(name: string, department: string) {
super(name)
this.department = department;
}
public getElevatorPitch() {
return `Hello, my name is ${this.name} and I work in ${this.department}.`;
}
}
let howard = new Employee("Howard", "Sales");
console.log(howard.getElevatorPitch());
console.log(howard.name); // error
在Typescript中,可以使用ES6很多新的特性,其中类Class也是ES6特性之一。包括getter和setter,其实都是ES6而不是Typescript的特性。 但public、private、protected等,则是Typescript中增加的。
大多数情况下,类型声明包的名字总是与它们在npm上的包的名字相同,但是有@types/前缀:
npm install -D @types/node
这里我们参考node.d.ts中的require,在我们在typescript中使用require的时候,若无安装@types/node或是自己声明,会报错的:
// 声明require
declare var require: NodeRequire;
interface NodeModule {
exports: any;
require: NodeRequireFunction;
id: string;
filename: string;
loaded: boolean;
parent: NodeModule | null;
children: NodeModule[];
}
tsconfig.json:文件中指定了用来编译这个项目的根文件和编译选项。 tslint.json:规则定义。
// 常见tsconfig.json
{
"compilerOptions": {
"baseUrl": "src", // 根路径,常在使用paths时候结合使用
"target": "es6", // 目标js版本,当需要承接jsx的时候可设为"es6",常设为"es5"
"jsx": "preserve", // 保留jsx的处理,常用在使用jsx时
"module": "commonjs",
"sourceMap": true,
"emitDecoratorMetadata": true, // 使用装饰器
"experimentalDecorators": true, // 使用元数据
"lib": [
"dom",
"es7",
"es6"
],
"paths": {
"utils": "utils"
}
},
"exclude": [
"node_modules"
]
}
常用迁移步骤:
刚开始,项目比较小,我一个人写,每行代码我都能记得,每个变量我都知道是什么。
后来,我有了个小弟,他进来后熟悉项目全靠注释、README以及面对面讲解。我们开始愉快的合作节奏,分工进行与后台接口的对接,除了约定一些接口规范,我们通常只有一个初始版本的接口说明,联调中持续的更新并不能及时更新到文档或注释中。
再后来,又来了个小弟,我们开始了口口相传的说明。但是由于理解、表达和沟通的问题,效率开始下降。
我们每个人有各自的命名习惯,有的喜欢小驼峰,有的喜欢下划线,有的还爱用$。然后我们使用eslint,但是很多对象的属性、接口的类型等等,都无法解决。
我们使用不一样的编辑器,有VSCode,有WebStorm,有subline。
我们还经常出现接口调整,甚至是字段名调整的情况。
然后我们上了Typescript。
当时我们的框架是AngularJS(Angular1版本),但是也照样使用了ts。从js迁移到ts是其中一个小弟完成的,然后我们开始了制定一些规范,更新README说明。
后面的情况是:
我们对每个接口和数据对象定义interface,缺少相关的库类型定义也能从相关社区中找到。
不管我们使用怎样的编辑器,都能有很好的自动补全功能、导航工具。
接手相互的代码,能第一眼就能知道各个变量的类型,模块大致的作用等。
再也不怕经常性的调整接口,因为我们可以一键重构相同interface中的某字段。
接口的引入,使得我们对代码的抽象设计变得容易了,逻辑和架构也清晰了。
以上的这些这些,随着项目增大越发觉得舒服。
很多时候,当我们维护不同重量级的应用,或是在不同的场景中使用应用的时候,面对的架构选择往往是不一样的。 就像我们在很小的页面里使用redux会觉得繁琐,在数据类型不多的对象或接口中使用typescript会觉得没啥效果一样,个人还是认为,好的架构在能遇见拓展性的同时,不过度设计,恰到好处才是最棒的。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。