typeScript 基础篇 | 8月更文挑战

202 阅读5分钟

这是我参与8月更文挑战的第1天,活动详情查看: 8月更文挑战

首先来介绍下什么是 typeScript;根据官方定义,它是拥有类型系统的javascript的超级,可以编译成纯javascript。

1、类型检查;

typescript在编译代码时会进行严格的静态类型检查;这样,在编码阶段进行代码检查,不必将问题带到线上去。

2、语言扩展;

es6、异步操作、装饰器;借鉴其他语言特性,如 接口、抽象类等。

3、工具属性;

可以编译成标准的javascript,可以在任意浏览器上、操作系统上运行,无需任何运行时的额外开销。

一、数据类型

ts 在 js 的基础上新增了  void、any、never、元祖、枚举、高级类型。

共如下所示:

Boolean、Number、String、Array、Function、Object、Symbol、undefined、null、void、any、never、元祖、枚举、高级类型。

首先,要了解一个概念:类型注解。

作用:相当于强类型语言中的类型声明;

语法:(变量 / 函数):type

// 原始类型
let bool: boolean = true;
let num: number = 123;
let str: string = 'abc';

// str = 123  // 不被允许

将str 赋值 123 (number类型)是不被允许的 。

声明数组类型有两种方式:

下面表示声明元素是number类型的数组:

let arr1: number[] = [1,2,3];
let arr2: Array<number | string> = [1,2,3,'23'];

元祖

let tuple: [number, string] = [0, '1'];
tuple.push(2);
console.log(tuple);
tuple[2]; 
// 可以为元祖添加元素 ,但是不能越界访问;不建议使用

函数

let add = (x:number,y:number) => x + y;
let compute: (x: number,y: number) => number;
compute = (a,b) => a + b;

对象

let obj: {x: number,y: number} = {x: 1, y: 2};
访问对象
obj.x = 3;

symbol

let s1: symbol = Symbol();
let s2: Symbol();
s1 === s2 // false

undefined、null

let un: undefined = undefined;
let nu: null = null;
num = undefined;
num = null;
// 如果在 tsconfig.json 里面设置: "strictNullChecks": false 则可以赋值成功。

void 

一种操作符,可以让任何表达式返回undefined;如:void 0;

因为 undefined 在js中不是一个保留字,我们甚至自定义一个undefined去覆盖全局的undefined;如下代码:

(function () {
    var undefined = 0;
    console.log(undefined)
})()
// 0 
显然,在这个闭包中,undefined 覆盖了全局的undefined

所以,void 可确保函数返回值一定是undefined。

any 类型,可任意赋值

never:表示永远不会有返回值的类型。

1、一个函数抛出了异常,那么它就永远不会有返回值;

2、死循环函数

枚举类型

用户中台系统经常会遇到判断用户多身份的时候,那么如下代码你肯定不陌生。

function initByRole(role){
    if(role ===1 || role === 2){
        // doing
    }else if(role === 3 || role === 4){
        // doing
    }else if(role === 5){
        // doing
    }else{
        // doing
    }
}

可读性差;很难记住数字的含义;

可维护性差;硬编码,牵一发动全身;

这时候,可以借助ts中枚举类型。所谓枚举,指一组有名字的常量集合。可以联想手机里的通讯录,手机号存设名字后,拨打只需要找人,无需记住电话号码,后期电话号码更换,也不影响。

枚举类型分为:

1、数字枚举;

2、字符串枚举;

// 数字枚举 取值默认从0开始,后面的枚举成员值会递增。若设置初始值2,后面从2开始递增。枚举是通
过反向映射的原理实现的。enum Role {    Reporter=2, // 则后面依次是3456    Developer,    Maintainer,    Owner,    Guest}
console.log(Role.Reporter) // 0
// 字符串枚举enum Message {    Sucess = '恭喜,success!',    Fail = 'fail,失败了!'}// 字符串枚举enum Message {    Sucess = '恭喜,success!',    Fail = 'fail,失败了!'}
// 异构枚举enum Answer {    N,    Y = 'yes'}
// 枚举成员enum Char {    // const    a,    b = Char.a,    c = 1 + 3,    // computed    d = Math.random(),    e = '123'.length}
// 常量枚举const enum Month {    Jan,    Feb,    Mar}let month = [Month.Jan, Month.Feb, Month.Mar];console.log(month);
// 枚举类型enum E { a, b };enum F { a = 0, b = 1};enum G { a = 'ee2qwca', b = 'bannana' };let e: E = 3;let f: F = 3;// e === flet e1: E.a = 1;let e2: E.b;// e1 === e2
let e3: E.a = 2;// e1 === e3let g1: G = G.a;let g2: G.a;

接口,用来约束 函数、对象、以及类的结构和类型,这是一种代码协作的契约,我们必须遵守,而且不能改变。

对象类型的接口定义;

例:获取一组数据,把它渲染都页面居中。

可以用 interface 定义 list 接口,这个接口包括两个成员,id 和 name ;再定义一个result,他有一个成员,data,成员的取值就是 List 数组。接下来定义一个渲染函数,在这个函数中,遍历 result.data , 控制台输出 id 和 name 。假设 result 是从后端接收的数据,数据格式符合我们的定义,如下代码:

interface List {
    id: number;
    name:string;
}
interface Result {
    data: List[]
}
function render(result: Result){
    result.data.forEach((value) => {
        console.log(value.id, value.name)
    })
}
let result = {
    data: [
        {id: 1, name:'A', sex: 'male'},
        {id: 2, name: 'B'}
    ]
}
render(result)

实际开发中,后端往往会传过来一些约定之外的字段,ts 也是允许的,因为ts采用了一种鸭式变形法,一种动态语言类型风格。只要传入的对象满足接口的必要条件,那就是被允许的。但是如果用对象字面量则会报错,这时候

1、把对象字面量赋值给一个变量;如上 render(result);
2、类型断言;明确的告诉编译器,我们这个类型就是 Result ;
render({
    data: [
        {id: 1, name: 'A', sex: 'male'},
        {id: 2, name: 'B'}
    ]
} as Result);

或者
render(<Result>{
    data: [
        {id: 1, name: 'A', sex: 'male'},
        {id: 2, name: 'B'}
    ]
});
3、字符串索引签名
interface List {
    readonly id: number; // 只读属性
    name: string;
    [x: string]: any;
    age?: number // 可选属性
}

以上接口属性的个数都是固定,当你不确定一个接口中有多少个属性的时候,就可以使用可索引类型的接口。可索引类型的接口,可以用数字去索引,也可以用字符串去索引。

数字索引的接口:

interface StringArray {
    [index: number]: string
}
let chars: StringArray = ['A','B'];

字符串索引的接口

interface Names {
    [x: string]: string;
    // y:number; 不被允许
    [z: number]: string;
}