初探TypeScript

何谓TypeScript?

首先,我们需要对TypeScript有一个初步的认识:TypeScript是JavaScript的一个超集,它支持ES6、提供了类型系统,一定程度上便捷了我们的开发和调试工作。

为什么用TypeScript

TypeScript的定位是静态类型语言,而不是类型检查器;JavaScript作为一门解释型语言,在动态数据类型的变量中,很可能出现在编译过程中,因为数据类型问题而把时间耗费在debug过程中,大大降低了开发效率;TypeScript的类型机制,能让开发者通过对类型监控程度的控制,大大减少甚至杜绝由变量类型引起的报错;这种开发手段,在构建大型项目或多人协作项目上,都能起到很好的正面作用。

TypeScript配置文件

tscconfig.json文件示例代码:

{
    "compilerOptions": {
        "module": "commonjs",
        "noImplicitAny": true,
        "removeComments": true,
        "preserveConstEnums": true,
        "sourceMap": true
    },
    "include": [
        "src/**/*"
    ],
"exclude": [
        "node_modules",
"**/*.spec.ts"
    ]
 } 

 这里的compilerOptions可以忽略,因为编译器有默认值,files则是指明一个包含文件的相对路径或绝对路径的文件列表。

TypeScript的类型

TypeScript中声明变量时,可同时定义变量值的类型:

//类型包含number,undefined,Boolean,string,any,never,Array<type>等。。

//字符串类型

let _string: string = "hello world!";

//这是个字符串类型

let _array: Array<number> = [1,2,3];

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

 //undefined类型

let _undefined: undefined = undefined;

 //null类型

let _null: null = null;   

 //布尔型

let _boolean: boolean = true;

 //数字类型

let _num: number = 1;  

//任何类型都可,无限制(当声明变量时未定义类型,也会默认为any类型)

let _any: any = "any";  

//多种类型也可

let _manyType: number | string;

_manyType = 1;  //成立

_manyType = "hello world!"; //成立

//枚举类型

enum Color {Red, Green, Blue}

let c: Color = Color.Green

;console.log(c);  // 1

let colorName: string = Color[1];

console.log(colorName);   // Green

//never类型 

表示永不存在的值的类型,如抛出异常或无返回值的函数表达式或箭头函数表达式的返回类型

function error(message: string): never {
      throw new Error(message);
}

//元组  表示数组_tuple[0]必须为数字类型,_tuple[1]必须为字符串类型

let _tuple: [number, string] = [1, "hello world!"];

TypeScript的类

我们可以在TypeScript中使用面向对象模式进行编程,允许使用继承(extends)来扩展现有的类;

TypeScript里的成员都默认为public,被声明为private的成员不能被外部访问;

TypeScript中,派生类中可通过实例方法访问父类的protected成员,但无法使用;

构造函数能被标记为protected,这时候,这个类仅能在包含它的内实例化,但仍能被继承;

class Person {

    protected name: string;

    protected constructor(theName: string) { this.name = theName; }

}

// Employee 能够继承

 Personclass 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");

let john = new Person("John"); 

// 错误: 'Person' 的构造函数是被保护的.

下面先做一个简单的例子:

class Greeter {

    name: string;

    constructor(people: string){

        this.name = people;

    }

    say(toSomeone: string) {

        console.log("----This is Greeter----");

        console.log(`${this.name} say hello to ${toSomeone}.`);

    }

}

class GreeterTwo extends Greeter {

    constructor(name: string) {

        super(name);

    }

    say(toSomeone = "jimmy") {

        console.log("----This is GreeterTwo----");

        super.say(toSomeone);

    }

}

class GreeterThree extends Greeter {

    constructor(name: string) {

        super(name);

    }

    say(toSomeone = "tom") {

        console.log("----This is GreeterThree----");

        super.say(toSomeone);

    }

}

let first = new GreeterTwo("jackey");let sec: Greeter = new GreeterThree("john");

first.say();

sec.say("brand");

/*输出结果:

*----This is GreeterTwo----

*----This is Greeter----

*jackey say hello to jimmy.

*----This is GreeterThree----

*----This is Greeter----

*john say hello to brand.

*/

GreeterTwo和GreeterThree均重写了继承自Greeter的say方法;

声明sec时,虽然sec被定义为Greeter类型,但因为sec的值是GreeterThree,所以sec.say()最终还是会调用GreeterThree中重写的say方法。

TypeScript接口

TypeScript的核心原则之一是对值所具有的结构进行类型检查。 它有时被称做“鸭式辨型法”或“结构性子类型化”。 在TypeScript里,接口的作用就是为这些类型命名和为你的代码或第三方代码定义契约。

这是一个简单的TypeScript接口示例:

function printLabel(labelledObj: { label: string }) {  console.log(labelledObj.label);
}
let myObj = { size: 10, label: "Size 10 Object" };printLabel(myObj);

 对接口重写,实现要求:必须包含一个label属性且类型为string

interface LabelledValue {
  label: string;
}
function printLabel(labelledObj: LabelledValue) {
  console.log(labelledObj.label);
}
let myObj = {size: 10, label: "Size 10 Object"};
printLabel(myObj);

可选属性的接口(其实就是多了个问号   ?  )

可选属性有这么些好处:对可能存在的属性进行预定义;捕获引用了不存在的属性时的错误

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"});

总结

最后,个人感觉而言,TypeScript在编译时候进行类型检查,能有效避免运行时候才发现的类型错误,有效减少debug的工作,而且类型信息有利于后续维护工作的进行,IDE也能达到自动补全/检查等效果,也能提高代码的可读性。但不足在于,学习成本上可能需要些时间,引入第三方JS库的时候,一般都不会有.ts文件。

---------------------------------------------------------------

原文作者:腾讯工程师陈坤祥。

来源:腾讯内部KM论坛。

本文分享自微信公众号 - 腾讯NEXT学位(NextDegree)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-08-15

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 编程新手:看懂很多示例,却依然写不好一个程序

    腾讯NEXT学位
  • 干货|小程序性能优化的几点实践技巧

    “ 我们都知道,性能的好坏直接影响用户的体验。本文首先论述下如何评判一个小程序页面的性能情况,之后通过具体的案例重点讲解下几点实践技巧,最后再讲讲key值在渲...

    腾讯NEXT学位
  • 一看就晕的React事件机制

    腾讯NEXT学位
  • 【iOS开发】两个函数搞定本地存储

    平时我们经常会采用 NSUserDefaults 或者 Plist 来存储数据到设备,这样即使 App 被关闭,下次再打开的时候数据还在。这里我写了两个函数来...

    KyXu
  • Elementui tabs组件内添加组件

    siderBar和tab-bar在同一个组件内,所以要实现参数传递,需要先emit提交事件,再在父组件传递给另一个子组件,这样链路就完整了,没看懂我的看下面的参...

    老梁
  • Unicode转中文,Unicode编码转换,ASCII转Unicode,Unicode转ASCII

    vivec
  • 如何选择腾讯云服务器配置?

    云服务器的配置选择,和网站或应用的类型、访问量、数据量大小、程序质量等因素有关,建议和您的网站或应用的开发技术人员沟通,选择最适合您的配置。

    用户6444356
  • 如何选择腾讯云服务器配置

    云服务器的配置选择,和网站或应用的类型、访问量、数据量大小、程序质量等因素有关,建议和您的网站或应用的开发技术人员沟通,选择最适合您的配置。

    用户5908769
  • 如何选择腾讯云服务器配置

    云服务器的配置选择,和网站或应用的类型、访问量、数据量大小、程序质量等因素有关,建议和您的网站或应用的开发技术人员沟通,选择最适合您的配置。

    用户5908769
  • 如何利用配置中心规范构建PaaS服务配置

    在上一篇文章中,我们以MQ和ACM为例,讨论了如何借助配置中心对消息进行限流管理的场景。在本文中,我们继续以该场景为例,讲述如何以规范的配置命名格式来进行限流设...

    用户1263954

扫码关注云+社区

领取腾讯云代金券