TypeScript笔记(一)

Tl;dr

这会是一篇很长的博文,大部分内容都直接来自Reference当中的TypeScript教程和ES6教程,只是为了总结一些自己认为重要的知识点,以及一些认为需要深入理解的地方及其延伸的链接,希望有帮助。

1. Intro

1.1 定义

  • JavaScript超集,提供了类型系统和对ES6的支持,由Microsoft开发

1.2 优势

  • 增加代码的可读性和可维护性
    • 类型系统是很好的文档,看类型的定义我们就能够知道如何使用了
    • 可以在编译阶段发现大部分错误,比运行时出错好很多
    • 增强编辑器的功能,包括代码补全,接口提示,跳转到定义,重构等
  • 兼容性好
    • js文件实际上是可以直接重命名为ts文件的
    • 及时不显式定义类型,也能够自动做出类型推论

1.3 相对劣势

  • 学习成本
    • 接口
    • 泛型
  • 短期增加开发成本,要多写一些类型的定义,但是对于需要长期维护的项目,TypeScript能够减少其维护成本
  • 集成到构建流程当中需要一些工作量的

2. 基础知识

2.1 原始数据类型

  • 布尔值 - boolean

      let isSuccessful: boolean = true;
    
      let createdByNewBoolean: boolean = new Boolean(1);
      // Type 'Boolean' is not assignable to type 'boolean'.
      // 'boolean' is a primitive, but 'Boolean' is a wrapper object. Prefer using 'boolean' when possible.
    
      let createdByNewBoolean: Boolean = new Boolean(1);
      // when you new Boolean, it will create a Boolean - a wrapper object
    
      let createdByBoolean: boolean = Boolean(1); 
      // create a boolean 
  • 数值 - number

      let decLiteral: number = 6;
  • 字符串 - string

    let myName: string = 'Tom';
    let myAge: number = 25;

    // 模板字符串  `用来定义模板字符串,${}用来在模板字符串中嵌入表达式
    let sentence: string = `Hello, my name is ${myName}.
    I'll be ${myAge + 1} years old next month.`;
  • null & undefined
    • null 和 undefined是所有类型的子类型
    • void类型的变量不能赋值给number类型的变量
  • symbol

2.2 任意值 - Any

任意值用来表示允许赋值为任意类型。在Typescript当中,普通类型在复制过程中改变类型是不被允许的,但是如果是any类型,则允许被赋值为任意类型。

    let myFavoriteNumber: any = 'seven';
    myFavoriteNumber = 7;
  • 任意值上访问任何属性都是允许的,也允许调用任何方法
  • 返回的类型都是任意值
  • 对于未声明类型的变量
    • 未指定类型,那么会被识别为任意值类型

2.3 类型推论

如果没有明确的指定类型,那么TypeScript会按照类型推论 - Type Inference的规则推断出一个类型。

let myFavoriteNumber = 'seven';
myFavoriteNumber = 7;

// index.ts(2,1): error TS2322: Type 'number' is not assignable to type 'string'.  编译的时候出错,因为TS自动做了类型推论,并且认定其为一个string类型

但是如果定义的时候没有赋值,那么不管接下来是否会赋值,都会被推断成any类型而完全不被类型检查

let myFavoriteNumber;
myFavoriteNumber = 'seven';
myFavoriteNumber = 7;

2.4 联合类型 - Union Types

let myFavoriteNumber: string | number;
myFavoriteNumber = 'seven';
myFavoriteNumber = 7;

联合类型当中使用 |来分割每个类型

2.5 接口

  • 在TypeScript当中,使用接口定义对象的类型,除了可以对类的一部分行为进行抽象以外,也chang’yo个与对 对象的形状进行描述。

    interface Person {

      name: string;
      age: number;

    }

    let tom: Person = {

      name: 'Tom',
      age: 25

    };

在做赋值的时候,定义的变量需要和接口有一样的属性。

  • 对于我们想要可选择的匹配的属性,我们可以用可选属性的方式:

    interface Person {

      name: string;
      age?: number;

    }

    let tom: Person = {

      name: 'Tom'

    };

  • 也可以配置,是的接口能够接任意的属性: – [propName: string] : any

    • 需要注意的是一旦定义了任意属性,那么确定属性和可选属性的类型都必须是它的类型的子集

      interface Person {
      name: string;
      age?: number;
      [propName: string]: any;
      }

      let tom: Person = {
      name: ‘Tom’,
      gender: ‘male’
      };

  • 只读属性

    • 有use case我们希望对象当中的一些字段只能在创建的时候被赋值,那么就可以通过使用readonly定义只读属性

2.6 数组类型

  • 使用类型+方括号来定义
let fibonacci: number[] = [1, 1, 2, 3, 5];
  • 使用数组泛型来表示数组 – Array<elemType>
let fibonacci: Array<number> = [1, 1, 2, 3, 5];
  • 使用接口表示数组
interface NumberArray {
    [index: number]: number;
}
let fibonacci: NumberArray = [1, 1, 2, 3, 5];

2.7 函数类型

2.7.1 函数声明

// 函数声明(Function Declaration)
function sum(x, y) {
    return x + y;
}

// 函数表达式(Function Expression)
let mySum = function (x, y) {
    return x + y;
};

// TypeScript下的函数声明
function sum(x: number, y:number):number {
    return x + y;
}

2.7.2 函数表达式

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

注意在上述代码当中,跟在mySum后面的是对于输入参数和输出参数的规定,中间用箭头来进行连接,这是TypeScript的规范。

另外我们也可以通过使用接口来定义函数的形状:

interface SearchFunc {
    (source: string, subString: string): boolean;
}

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

2.7.3 可选参数

  • 使用问号跟在参数名字之后表示是可选的,注意可选参数需要在参数列表的末尾,其之后不能有必需参数了
function buildName(firstName: string, lastName?: string) {
    if (lastName) {
        return firstName + ' ' + lastName;
    } else {
        return firstName;
    }
}

2.7.4 参数默认与剩余参数

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

// 使用 ...来获取函数当中的剩余参数
function push(array, ...items) {
    items.forEach(function(item) {
        array.push(item);
    });
}

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

2.8 声明文件

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

2.8.1 声明语句

比如我们想使用jquery,一般来说是加script标签,但是ts当中,我们需要使用declare var来定义其类型

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

jQuery('#foo');

我们会将声明语句放到一个单独的文件当中,譬如对于上述的例子,就是放到jQuery.d.ts 当中
声明文件必须以.d.ts来结尾

ts会解析项目当中所有的*.ts文件,也包含了.d.ts结尾的文件,所以当我们定义.d.ts文件以后,里面的内容是会被整个项目共享的。

另外,我们可以通过@types 来统一管理第三方库的声明文件

2.8.2 书写声明文件

当第三方库没有提供声明文件的时候,我们就需要自己书写声明文件了。

库的使用场景主要有:

  • 全局变量
  • npm包
  • UMD库
  • 直接扩展全局变量

详情看 link

2.9 内置对象

ECMAScript 内置对象

DOM DOM 内置对象

Reference

  1. https://ts.xcatliu.com/
  2. https://es6.ruanyifeng.com/

转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 stone2paul@gmail.com

文章标题:TypeScript笔记(一)

文章字数:1.8k

本文作者:Leilei Chen

发布时间:2020-04-19, 10:44:45

最后更新:2020-04-20, 20:26:13

原始链接:https://www.llchen60.com/TypeScript%E7%AC%94%E8%AE%B0-0/

版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。

目录
×

喜欢就点赞,疼爱就打赏