TypeScript的应用方式

> 本文不讲如何安装,只讲代码中的实际应用

# 一、什么是 TypeScript?

typescript是js的超集,它在js的基础上增加了静态类型校验,可以在运行前校验js中的一些错误并修正。

在定义类型之后,js中任何地方都会有文档提示,对象中包含的值都可以提示出来,这一点让js变得相当友好。

那么想要在已有项目中增加ts需要怎么做?

ts支持渐进式迁移,可配置只检查部分文件,在已有项目中慢慢改造。ts的类型检查不会影响js代码的执行、这意味着,即便类型校验有错误,代码依旧运行良好。

ts的困难在于它需要定义所有的值类型,这个工作量还是蛮大的。

# 二、ts的简单使用

**ts的类型定义语法如下**

- 基础类型:

```javascript

let isDone: Boolean = false;

let str: String = '';

let count: Number = 1;

// 使用联合操作符

let some1: Number | String = 1;

let some2: Number | String = '1';

```

- 数组

```javascript

let arr1: number[] = [1,2];

let arr2: Array<string> = ['1','2']; // 泛型写法,下面会讲

let arr3: [string,boolean] = ['1',false]; // 元组-定义已知数量和类型

```

- 对象(当存在复杂对象时,使用接口和类来声明,后面会讲)

```javascript

let obj: {a: string, b: number } = {a: '我是字符串',b: 2};

```

- any

```javascript

let something: any = 'asd';

```

any用来表示任何类型,ts不会对它进行校验。

>  如果你的ts代码中到处都是any,建议不要使用ts更方便些。

- viod、null、undefined、never

这些值基本没什么用,有兴趣可以自己查看[文档](https://www.tslang.cn/docs/handbook/basic-types.html)

- 枚举 **enum**

**enum**类型是对JavaScript标准数据类型的一个补充。 使用枚举类型可以为一组数值赋予友好的名字。

```javascript

enum Color {Red, Green, Blue} // 默认情况下,从0开始为元素编号。

let c: Color = Color.Green; // => 1

//你也可以手动的指定成员的数值。 例如,我们将上面的例子改成从 1开始编号:

enum Color {Red = 1, Green, Blue}

let c: Color = Color.Green; // => 2

```

它不但可以使用key获取value,还可以使用value获取key。

```javascript

enum Color {Red=1, Green, Blue}

let colorName: string = Color[2]; // => 'Green'

```

# 三、ts进阶使用

## 类型断言

当你确定某个值的类型时,你可以指定它的类型。它有两种写法:

尖括号写法

```javascript

let someValue: any = "this is a string"; // any未知类型

let str: string = someValue; // error someValue不是string类型

// 断言为string,校验成功

let str: string = <string>someValue;

```

as写法

```javascript

let someValue: any = "this is a string";

let str: string = someValue as string

```

## 接口interface

interface用来定义复杂类型(对象、函数、索引类型等)

```javascript

interface Config {

  readonly color: string; // 定义只读

  width?: number; // 定义可选属性

}

function doSome( option: Config ){

  // option.color

  // option.width

}

```

同一作用域中同名的interface会自动合并

```javascript

interface Config {

  color: string;

  width: number;

}

// 同一作用域中

interface Config {

  height: number;

}

// 会合并为

interface Config {

  color: string;

  width: number;

  height: number;

}

```

extentds (interface可以使用extentds进行拓展)

```javascript

interface Parent{

  readonly color: string; // 可定义常量

  width: number;

}

interface Children extends Parent{

  height: number;

}

```

## 类

公共,私有 与 存取

1、public

```javascript

class Animal {

    name: string; // 默认为public

    public id: string; // 也可以标明public

}

```

2、private

```javascript

class Animal {

    // private 禁止在类的外部访问

    private move() {

// dosomething

    }

}

new Animal().move; // 错误: 'move' 是私有的.

```

3、get、set

TypeScript支持通过getters/setters来截取对对象成员的访问。与vue的watcher同理。

```javascript

class Animal {

    get fullName(): string {

        return this._fullName;

    }

    set fullName(newName: string) {

        // dosomething

    }

}

```

4、readonly标明只读

```javascript

class Animal {

    readonly number: number = 8;

}

```

还有static、protected等,这里不过多说明,详情请看[文档。](https://www.tslang.cn/docs/handbook/classes.html)

## 函数

函数类型包含两部分:参数类型和返回值类型。

```javascript

// :number 表示返回值为number

function add(x: number, y: number): number {

    return x + y;

}

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

```

声明一个未赋值函数

```javascript

let fn: (x: number, y: number) => number;

fn = myAdd;

```

除此之外,interface同样可以声明函数类型

```javascript

// : boolean表示返回值为布尔值

interface Func {

  (source: string, subString: string): boolean;

}

// 命名为x,y或者其他都可以

let ff: Func = (x: string, y: string): boolean => {

return x === y

}

```

函数参数类型只会校验它的类型,不会校验它的名字

## type类型别名

类型别名会给一个类型起个新名字。它可以作用于原始值,联合类型,元组以及其它任何你需要手写的类型。它的语法看起来像是普通的js。

```java

// 给String重新命名

type Easing = String

// 定义联合类型

type Easing = 'a' | 'b' | 'c'

```

type可以将多个interface联合或者交叉

```java

interface A{

    kind: "square";

    size: number;

}

interface B{

    kind: "rectangle";

    width: number;

    height: number;

}

interface C{

    kind: "circle";

    radius: number;

}

type Shape1 = A | B | C; // 联合

type Shape2 = A & B & C; // 交叉

```

type也可以声明函数和元组

```java

// 函数

type Easing = () => string

// 元组

type DudeType = {

  [key in Keys]: string // keys是一个索引类型

}

```

> type和interface功能类似,但type更像一个值而不是一个类型。在两者都能实现需求的情况下,官方建议优先使用interface。

# 四、ts高级用法--泛型

考虑到代码的可重用性和拓展性,ts允许使用泛型来定义未知类型,使用尖括号语法。

```javascript

// 当入参未知时,我们可定义一个泛型

function identity<T>(arg: T): T {

    return arg;

}

// 它可以这样用,表示数组

function identity<T>(arg: T[]): T[] {

    return arg;

}

// 或者表示对象

function identity<T>(arg: {x: T, y: T}): T {

    return arg.x;

}

```

泛型支持extends语法

```javascript

interface Lengthwise {

    length: number;

}

function loggingIdentity<T extends Lengthwise>(arg: T): T {

    console.log(arg.length);  // 可以用时length属性

    return arg;

}

```

泛型promise使用示例

```typescript

// Promise<T>表示Promise.resolve的值类型是T

// catch类型默认是any

let ajax = <T>(params: any): Promise<T> => {

  return new Promise((resolve) => {

    axios.get('/list').then(res=> {

      resolve(params)

    })

  })

}

// 使用时

ajax<{a: string,b:number}>(params).then(res=>{

    // res 类型为{a: string,b:number}

)

```

>此处只讲了typescript的一些常见用法和问题,更多说明请看官方文档。[(中文文档3.1](https://www.tslang.cn/docs/release-notes/typescript-3.1.html),[英文文档4.1)](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-1.html)

==一些运算操作符==

1. !断言此处有值。

```javascript

let y!:number = 1; // 表示y必定有值

```

2. ?表示可能未定义。

```javascript

let obj = {

    y?: number, // 相当于  number | undefined

    z: string

}

let num: number;

num = obj.y; // error,不能将类型“number | undefined”分配给类型“number”。

```

3. ?? 空值合并。

通常我们取一个可能存在的值时,会像这样

```javascript

let obj = {

    y?: number

}

let num: number;

num = obj.y || 1;

```

但当obj.y为0时,它会存在问题。所以ts提供了更好的解决方案。??只会判断null和undefined两个值。

```javascript

let obj = {

    y?: number

}

let num: number;

num = obj.y ?? 1; // 即使y为0,也会得到0,而不是1

```

4.!取值用法和?的赋值用法。

!表示必定有值,?表示可能有值,所以他们也可以这样使用

当你确定值必定存在时

```javascript

let obj: {

    a?: {

          b?: number

}

} = { a: { b: 1 } };

let x: number = obj.a.b; // 报错,对象可能未定义

let y: number = obj!.a!.b; // 通过

```

当你不确定值是否存在

```javascript

let obj: {

      a?: {

        b?: number

      }

    }

obj.a.b = 1; // 报错

obj?.a?.b = 1; // 通过

```

5. !(放在value之后)允许null和undefined

```javascript

let y:number

y = null // 无法通过编译

y = undefined // 无法通过编译

y = null!      // 通过

y = undefined! // 通过

```

6. 最新特性??=、||=、&&= 

有时候我们需要对可能存在的值给一个默认值

```javascript

let obj = {

    y?: number

}

// 正常情况

obj.y = obj.y ? obj.y : 1;

// 使用??空值合并

obj.y = obj.y ?? 1;

// 使用??=运算符,他看起来有点像 +=和-=

obj.y ??= 1;

```

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,670评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,928评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,926评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,238评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,112评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,138评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,545评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,232评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,496评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,596评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,369评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,226评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,600评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,906评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,185评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,516评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,721评论 2 335

推荐阅读更多精彩内容