TS基础教程

234 阅读7分钟

什么是TypeScript?

  • TypeScript 是添加了类型系统的 JavaScript,适用于任何规模的项目。
  • TypeScript 是一门静态类型、弱类型的语言。
  • TypeScript 是完全兼容 JavaScript 的,它不会修改 JavaScript 运行时的特性。
  • TypeScript 可以编译为 JavaScript,然后运行在浏览器、Node.js 等任何能运行 JavaScript 的环境中。
  • TypeScript 拥有很多编译选项,类型检查的严格程度由你决定。
  • TypeScript 可以和 JavaScript 共存,这意味着 JavaScript 项目能够渐进式的迁移到 TypeScript。
  • TypeScript 增强了编辑器(IDE)的功能,提供了代码补全、接口提示、跳转到定义、代码重构等能力。
  • TypeScript 拥有活跃的社区,大多数常用的第三方库都提供了类型声明。
  • TypeScript 与标准同步发展,符合最新的 ECMAScript 标准(stage 3)。

基础

  • 字符串:string
let myName:string='Tom'; 
// 模板字符串
let str:string=`my name is ${myName}`
  • 数字:number
let num1:number=20; 
let num2:number=NaN;
let num3:number=Infinity;

数值可以是二进制 八进制等;

  • 布尔值:boolean
let editable=false;

注意Boolean构造函数创建的是Boolean对象,直接调用Boolean可以返回boolean类型,如:

let val=Boolean(1);
  • undefind 和 null
let u: undefined = undefined;
let n: null = null;

undefind和null是所有类型的子类型,如undefind类型的变量可以赋值给number类型的变量

  • 空值:void js中没有空值的概念,ts中用来表示没有任何返回值的函数
function alertName(): void {
    alert('My name is Tom');
}
  • 任意值:any

可以被赋值为任意类型:普通类型的变量是不允许被修改类型的,但是any类型可允许被赋值为任意类型。 在any类型上可以访问任何属性或调用任何方法,声明一个any类型后对改该类型进行任何操作,返回的内容的类型还是any类型。

let anyThing: any = 'hello';
console.log(anyThing.num)
anyThing.setNum(20)

任何变量在声明时未指定类型,则会被识别为任意类型。

let something;
something = 'seven';
something = 7;
something.setName('Tom');
  • 数组
let cnumber[] = [123];
const arrany[] = [1"33"true];
const dArray<number> = [13];  
  • 元组:为数组中的每个元素规定相应的类型
const arr: [numberstring] = [20"tom"];
  • 联合类型
let myFavoriteNumber: string | number;
myFavoriteNumber = 'seven';
myFavoriteNumber = 7;

联合类型使用|分割不同类型,当不确定联合类型具体是哪种类型时,只能访问几种类型共有的属性和方法,当被赋值的时候会根据类型推断规则推断出具体类型,此时只能访问该类型上的方法和属性,否则会编译报错;

  • 枚举类型 枚举使用enum关键字来定义
enum Days {Sun = 3, Mon = 1, Tue, Wed, Thu, Fri, Sat};

当枚举成员第一项未被赋值时会从0开始依次赋值,未被赋值的成员会从上一个成员值的基础上增1,(ps: 未手动赋值的成员值可能会与手动赋值的成员值相等,但ts察觉不到这一点)枚举成员的值也可不是数字,需要使用类型断言让ts忽视检查:

enum Days {Sun = 7, Mon, Tue, Wed, Thu, Fri, Sat = <any>"S"};
  • 对象-接口 ts中使用接口(Interfaces)来定义对象类型,接口是对行为的抽象,即一系列抽象方法的声明,是一些方法特征的集合,需要由具体的类去实现,然后第三方就可以通过这组抽象方法调用. ts除了对类的一部分行为进行抽象外,还会对类的形状进行描述.
interface Person {
    name: string;
    age: number;
}

let tom: Person = {
    name: 'Tom',
    age: 25
};

赋值的时候变量的形状必须和接口的形状保持一致,多一个或少一个属性或者属性类型不一致都是不被允许的.

当不希望完全匹配一个属性时,可以使用可选属性:

interface Person {
    name: string;
    age?: number;
}

let tom: Person = {
    name: 'Tom'
};

注意不允许出现未定义的属性

当希望接口有一个任意属性,可以使用任意属性:

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

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

注意:一旦定义了任意属性,那么确定属性和可选属性的类型都必须是它的类型的子集,实例中string和number类型是any的子类型,若将任意属性类型定义为string,将会编译报错,因为number不是any的子类型

一个接口中只能定义一个任意属性。如果接口中有多个类型的属性,则可以在任意属性中使用联合类型:

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

let tom: Person = {
    name: 'Tom',
    age: 25,
    gender: 'male'
};

只读属性

当我们希望对象中的一些字段只在创建的时候被赋值,那么可以用 readonly 定义只读属性:

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

let tom: Person = {
    id: 89757,
    name: 'Tom',
    gender: 'male'
};

tom.id = 9527;
// index.ts(14,5): error TS2540: Cannot assign to 'id' because it is a constant or a read-only property.

只读属性只能在接口定义时赋值,在其他过程中赋值或定义不赋值则会报错;

  • 函数 在js中函数申明有两种方式:函数声明和函数表达式
// 函数声明(Function Declaration)
function sum(x, y) {
    return x + y;
}

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

函数声明

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

注意函数表达式中mySum变量的类型定义为 (x: number, y: number) => number,在ts类型定义中=>表示函数的定义,左边是函数的输入定义且用括号包裹,右边是函数的输出类型;一般定义中会省略mysum类型定义,是通过赋值操作进行类型推论推断出的. 用接口定义函数的形状

我们也可以使用接口的方式来定义一个函数需要符合的形状:

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

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

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

可选参数

可选参数如接口定义中可选属性使用?来定义,函数参数定义中可选参数必须在必需参数之后,且后面不能再有必需参数.

function mySum(x: number, y: number,z?:number) {
    if (z) {
        return x+y+z;
    } else {
        return x+y;
    }
}
let sum = mySum(1,2);

默认参数

在 ES6 中,我们允许给函数的参数添加默认值,TypeScript 会将添加了默认值的参数识别为可选参数,此时就不受「可选参数必须接在必需参数后面」的限制了:

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

剩余参数

函数有多个参数时,可以把未定义的参数定义为数组

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

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

注意,...rest 参数只能是最后一个参数

函数重载

重载允许函数在接收不同类型或数量的变量时,做出不同的处理:

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

前两个是函数定义,最后一个是函数实现,会根据具体的变量类型返回应当返回的数据类型

  • 泛型 泛型是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性。

未完待续...

参考: