1
头图

前言

随着前端在各种类型的项目中扮演的角色越来越重要,人们发现 JavaScript 这门弱类型语言已经不能满足当下的需求,尤其是在一些大中型项目中,JavaScript 远远没有一些强类型语言用得顺手,而 TypeScript 因此诞生。

TypeScript 是什么?

简单来讲,TypeScriptJavaScript 的超集,它可以编译成纯 JavaScript

基础语法

基础类型

由于 TypeScript 是在 JavaScript 的基础上定义的,所以基础类型其实也是大同小异,这里仅列出来和 JavaScript 做一个对比。

  • 布尔值
    声明方式:let a: boolean = true
    对比:JavaScript 中也存在布尔值类型。
  • 数字
    声明方式:let a: number = 2
    对比:JavaScript 中也存在数字类型。
  • 字符串
    声明方式:let a: string = '233'
    对比:JavaScript 中也存在字符串类型。
  • 数组
    声明方式:let a: number[] = [1,2,3]
    对比:JavaScript 中也存在数组类型。
  • 元组 Tuple
    声明方式:let a: [number, string]
    对比:JavaScript 中不存在这种类型。
    说明:定义一个元组,相当于定义一个规定类型的数组;比如上面的变量 a ,前两个元素只能对应 number 类型和 string 类型,而之后的元素的类型也只能是 numberstring 中的一种。
  • 枚举
    声明方式:enum animal = {cat, dog, duck}let a: animal = animal.cat,跟其他语言一样,如果不赋值的话,枚举值从 0n,当然也可以选择手动赋值。
    对比:JavaScript 中不存在这种类型,不过枚举也可以简单的用声明常量的方式来代替。
  • Any
    声明方式:let a: any = '2333'
    对比:JavaScript 中不存在这种类型。
    说明:声明一个 any 类型的变量,通常它表示所有类型的变量。
  • Void
    声明方式:let gg: void = undefined
    对比:JavaScript 中存在 void,但它不是变量类型,而是一个操作符
  • Null
    声明方式:let a: null = null
    对比:JavaScript 中存在 Null 类型。
    说明:Null 类型可以看成其他类型的子类型,也就是说 Null 类型的变量也可以赋值给其他类型的变量并且不会报错。
  • Undefined
    声明方式:let a: undefined = undefined
    对比:JavaScript 中存在 Undefined 类型。
    说明:Undefined 类型同上面所说的 Null 一样,也是其他类型的子类型。
  • Never
    声明方式:无法声明,因为其他类型的变量不能给 never 类型的变量赋值。never 类型只能从函数返回值中获取。
    对比:JavaScript 中不存在 never 类型。
    说明:never 类型表示的是那些永不存在的值的类型。
  • Object
    声明方式:let a: object = {}
    对比:JavaScript 中存在 object 类型

接口

TypeScript 的核心原则之一是对值所具有的结构进行类型检查。 它有时被称做“鸭式辨型法”或“结构性子类型化”。 在 TypeScript 里,接口的作用就是为这些类型命名和为你的代码或第三方代码定义契约。

简单来说,接口(interface)存在的意义是为了对复杂类型(object)的存在进行约束。
比方说有一个对象 person,它有以下这些属性:

  • 姓名
  • 身高
  • 体重
  • ...
  • 由于 person 是一个复杂的对象,使用接口(interface)则可以对它进行一个严格的约束。比如:

    interface Person {
      name: string,
      height: number,
      weight: number
    }

    可选属性

接口里的属性不全都是必需的。 有些是只在某些条件下存在,或者根本不存在。 可选属性在应用“option bags”模式时很常用,即给函数传入的参数对象中只有部分属性赋值了。

可选属性 的存在其实跟你有没有男/女朋友的关系是一样的,有固然好,没有也不会怎么样。不过你要是男女通吃那我也拿你没办法...
以此为例子,我们拓展下上面的代码:

interface Person {
    name: string,
    height: number,
    weight: number,
    girlFriend?: object,
    boyFriend?: object
}

只读属性

如果有些属性只想赋值一次,那么只读属性就可以派上用场。

比方说我们的身高,在一定年龄后就不会再长,那么其实也可以把它近似的看成一个只读属性。

因此我们上面的代码也可以这样写。

interface Person {
    name: string,
    readonly height: number,
    weight: number,
    girlFriend?: object,
    boyFriend?: object
}

函数

JavaScript 一样,TypeScript 函数可以创建有名字的函数和匿名函数。 你可以随意选择适合应用程序的方式,不论是定义一系列 API 函数还是只使用一次的函数。

TypeScript 中的函数跟 JavaScript 在书写方式上区别并不算很大,比如说定义一个 add 函数:
使用 JavaScript 是这样写的:

function add(a, b) {
    return a + b
}

使用 TypeScript 是这样写的:

function add(a: number, b: number): number {
    return a + b
}

那么 TypeScript 的函数就没点其他的功能了吗?其实还是有的。

可选参数和默认参数
  • 可选参数:函数的参数可选
  • 默认参数:函数的参数设置默认值

可选参数的写法:

function foo(a: number, b: string, c?: boolean): void {
    console.log(a,b,c)
}
foo(1,'233') // 1, '233', undefined

设置了一个可选参数,如果不传值,那么它默认就是 undefined

默认参数的写法:

function foo(a: number, b: string, c = false): void {
    console.log(a, b, c)
}
foo(1,'gg') // 1, 'gg', false

这里的默认参数JavaScript 中的写法是等价的。

重载

函数重载意味着允许存在相同函数名,但是参数类型、个数、返回值其中的一个或多个不相同的函数。

当然,我们来看个简单的例子会更加清晰明了。比如说你的老大让你写一个 swap 函数,相信在座的各位前端er都能写出:

function swap(arr, i, j) {
    let tmp = arr[i]
    arr[i] = arr[j]
    arr[j] = tmp
    // [arr[i], arr[j]] = [arr[j], arr[i]] 利用解构也可以这样写
}

如果用 TypeScript 那就要指定参数 arr 的类型了,如果指定了 number[] 或者 string[] 之类的,那么未免太死板了;但是如果指定了 any 类型,那又没办法约束参数。而函数重载在这个时候就发挥了它的作用:

function swap(arr: number[], i: number, j: number)
function swap(arr: string[], i: number, j: number)
function swap(arr, i, j) {
    [arr[i], arr[j]] = [arr[j], arr[i]]
}

练习地址:https://www.tslang.cn/play/index.html

参考资料:

扫描下方的二维码或搜索「tony老师的前端补习班」关注我的微信公众号,那么就可以第一时间收到我的最新文章。


tonychen
1.2k 声望272 粉丝