TypeScript基础

TypeScript入门教程

写在前边

这只是一个笔记,并不是教程,阮一峰大佬写的教程链接在上边

函数

  • 函数声明定义

    function sum(x: number, y: number): number {
      return x + y;
    }

    输入多余的(或者少于要求的)参数,是不被允许的

  • 函数表达式定义

    let mySum: (x: number, y: number) => number = function (x: number, y: number): number {
      return x + y;
    };

    注意不要混淆了 TypeScript 中的 => 和 ES6 中的 =>。
    在 TypeScript 的类型定义中,=> 用来表示函数的定义,左边是输入类型,需要用括号括起来,右边是输出类型。
    在 ES6 中,=> 叫做箭头函数,应用十分广泛,可以参考 ES6 中的箭头函数。

  • 用接口定义函数的形状

    interface SearchFunc {
      (source: string, subString: string): boolean;
    }
    let mySearch: SearchFunc;
    mySearch = function(source: string, subString: string) {
      return source.search(subString) !== -1;
    }

    采用函数表达式|接口定义函数的方式时,对等号左侧进行类型限制,可以保证以后对函数名赋值时保证参数个数、参数类型、返回值类型不变。

  • 可选参数
    与接口中的可选属性类似,我们用 ? 表示可选的参数

    function buildName(firstName: string, lastName?: string) {
      if (lastName) {
          return firstName + ' ' + lastName;
      } else {
          return firstName;
      }
    }
    let tomcat = buildName('Tom', 'Cat');
    let tom = buildName('Tom');

    需要注意的是,可选参数必须接在必需参数后面。换句话说,可选参数后面不允许再出现必需参数了

  • 参数默认值
    TypeScript 会将添加了默认值的参数识别为可选参数

    function buildName(firstName: string, lastName: string = 'Cat') {
      return firstName + ' ' + lastName;
    }
    let tomcat = buildName('Tom', 'Cat');
    let tom = buildName('Tom');

    此时就不受「可选参数必须接在必需参数后面」的限制了

  • 剩余参数
    ES6 中,可以使用 ...rest 的方式获取函数中的剩余参数(rest 参数)

事实上,items 是一个数组。所以我们可以用数组的类型来定义它

function push(array: any[], ...items: any[]) {
    items.forEach(function(item) {
        array.push(item);
    });
}

let a = [];
push(a, 1, 2, 3);

rest 参数只能是最后一个参数

  • 重载

重载允许一个函数接受不同数量或类型的参数时,作出不同的处理。

比如,我们需要实现一个函数 reverse,输入数字 123 的时候,输出反转的数字 321,输入字符串 ‘hello’ 的时候,输出反转的字符串 ‘olleh’。

利用联合类型,我们可以这么实现:

function reverse(x: number): number;
function reverse(x: string): string;
function reverse(x: number | string): number | string {
    if (typeof x === 'number') {
        return Number(x.toString().split('').reverse().join(''));
    } else if (typeof x === 'string') {
        return x.split('').reverse().join('');
    }
}

上例中,我们重复定义了多次函数 reverse,前几次都是函数定义,最后一次是函数实现。在编辑器的代码提示中,可以正确的看到前两个提示。

注意,TypeScript 会优先从最前面的函数定义开始匹配,所以多个函数定义如果有包含关系,需要优先把精确的定义写在前面。

断言

使用 as 类型 的语法

interface Cat {
    name: string;
    run(): void;
}
interface Fish {
    name: string;
    swim(): void;
}

function isFish(animal: Cat | Fish) {
    if (typeof animal.swim === 'function') {  // 会报错,因为swim不是Cat和Fish的共有属性
        return true;
    }
    return false;
}

function isFish(animal: Cat | Fish) {
    if (typeof (animal as Fish).swim === 'function') { // 使用断言,避免错误
        return true;
    }
    return false;
}

类型断言只能够「欺骗」TypeScript 编译器,无法避免运行时的错误,反而滥用类型断言可能会导致运行时错误

window.foo = 1; // 直接赋值会提示你window上边没有foo属性
(window as any).foo = 1; // 把window断言成一个any就可以随便赋值了
  • 总结

联合类型可以被断言为其中一个类型

父类可以被断言为子类

任何类型都可以被断言为 any

any 可以被断言为任何类型

要使得 A 能够被断言为 B,只需要 A 兼容 B 或 B 兼容 A 即可

声明文件

当使用第三方库时,我们需要引用它的声明文件,才能获得对应的代码补全、接口提示等功能。

声明文件必需以 .d.ts 为后缀。

// src/jQuery.d.ts

declare var jQuery: (selector: string) => any;

假如仍然无法解析,那么可以检查下 tsconfig.json 中的 files、includeexclude 配置,确保其包含了 jQuery.d.ts 文件。

第三方声明文件

当然,jQuery 的声明文件不需要我们定义了,社区已经帮我们定义好了:jQuery in DefinitelyTyped。

我们可以直接下载下来使用,但是更推荐的是使用 @types 统一管理第三方库的声明文件。

@types 的使用方式很简单,直接用 npm 安装对应的声明模块即可,以 jQuery 举例

cnpm install @types/jquery --save-dev

可以在这个页面搜索你需要的声明文件。

书写声明文件

当一个第三方库没有提供声明文件时,我们就需要自己书写声明文件了。前面只介绍了最简单的声明文件内容,而真正书写一个声明文件并不是一件简单的事,以下会详细介绍如何书写声明文件。

内置对象

ECMAScript 标准提供的内置对象有:Boolean、Error、Date、RegExp 等。

let b: Boolean = new Boolean(1);
let e: Error = new Error('Error occurred');
let d: Date = new Date();
let r: RegExp = /[a-z]/;

更多的内置对象,可以查看 MDN 的文档

DOM 和 BOM 的内置对象

DOM 和 BOM 提供的内置对象有:Document、HTMLElement、Event、NodeList 等。

let body: HTMLElement = document.body;
let allDiv: NodeList = document.querySelectorAll('div');
document.addEventListener('click', function(e: MouseEvent) {
  // Do something
});

用 TypeScript 写 Node.js

Node.js 不是内置对象的一部分,如果想用 TypeScript 写 Node.js,则需要引入第三方声明文件:

npm install @types/node --save-dev


语言   ts      基础 ts

本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!