教程2:Typescript的变量类型介绍

179 阅读4分钟

前情提要

# 教程1:花费一分钟,跟着做,傻瓜式入门Typescript

类型注解

格式为:类型

举例

  1. let 变量: 变量类型
let uname: string; // 声明uname变量为string类型
let mySum: (x: number, y: number) => number // 对等号右侧的匿名函数进行了类型定义
  1. function fn (形参: 形参类型): 返回值类型 { ... }
function callName (uname: string): string {
    return '我的名字是' + uname
}

变量类型

number

let num: number = 10

string

let uname: string = 'lemon'

boolean

let isDone: boolean = false

字面量

let name: 'lemon' // name的值只能是'lemon'
let gender: 'male' | 'female' // gender的值只能是'male'或者'female
扩展:联合类型
// 联合类型: 表示一个值可以是几种类型之一,我们用竖线( |)分隔每个类型
// 如下:number | 'auto',表示一个值可以是 number, string,或 boolean。
let width: number | 'auto' // width的类型只能是number或者'auto'。

数组

  1. let 变量: 类型[]
  2. let 变量: Array<类型>
// 例如:
let numArr: number[]
let strArr: Array<string>

元组 Tuple

可以理解为长度固定的数组,每一项的元素类型均已声明且可不同

// 例如:
let x: [string, number]

当添加越界的元素时,它的类型会被限制为元组中每个类型的联合类型:

let tom: [string, number];
tom = ['Tom', 25];
tom.push(true);
// Argument of type 'true' is not assignable to parameter of type 'string | number'.

object

// 任意数组、函数都是对象,所以以下写法意义不大
let obj: object
// 扩展:可以改写成以下写法
let obj: { 
    name: string, // obj的值对应的对象必须要有name属性
    age?: number, // ?修饰符代表可选,obj的值对应的对象可以有age属性,也可以没有
    [propName: string]?: any // ES6对象扩展的语法: [propName]代表任意属性名
}

枚举

使用枚举类型可以为一组数值赋予友好的名字

// 枚举时,默认从0开始为元素编号。
enum Color {
    Red, // Color.Red = 0
    Green, // Color.Green = 1
    Blue // Color.Blue = 2
}
let c = Color.Green // 此时c的值为1
应用
// 假设res为后端返回颜色的数据
switch(res) {
    case Color.Red:
        ***;
        break;
    case Color.Green:
        ***;
        break;
    case Color.Blue:
        ***;
        break;
    default:
        ***;
}
​
// 或者在vue项目中
new Vue({
    data: {
        color: Color,
        res: 0 // res的值可变
    }
})
<span :style="{ color: color[res].toLowerCase() }">我没想好这里写啥</span>

any

表示任意类型。当你希望跳过类型检查时使用,不推荐使用。

let a: any
let b // 声明变量时不指定类型,则默认为any类型

void

void类型像是与any类型相反,它表示没有任何类型。 当一个函数没有返回值时,你通常会见到其返回值类型是 void

function warnUser(): void {
    console.log("This is my warning message");
}

声明一个void类型的变量没有什么大用,因为你只能为它赋予undefinednull

let unusable: void = undefined;

null 和 undefined

TypeScript里,undefinednull两者各自有自己的类型分别叫做undefinednull。 和 void相似,它们的本身的类型用处不是很大:

let u: undefined = undefined;
let n: null = null;

默认情况下nullundefined是所有类型的子类型。 就是说你可以把 nullundefined赋值给number类型的变量。

扩展(先了解)

前提:当你指定了--strictNullChecks标记(tsconfig.json配置后面会讲)

nullundefined只能赋值给void和它们各自。

也许在某处你想传入一个 stringnullundefined,你可以使用联合类型string | null | undefined

let s = "foo";
s = null; // 错误, 'null'不能赋值给'string'
​
let sn: string | null = "bar";
sn = null; // 可以sn = undefined; // error, 'undefined'不能赋值给'string | null'

TypeScript会把 nullundefined区别对待。

string | nullstring | undefinedstring | undefined | null是不同的类型。

never

never类型表示的是那些永不存在的值的类型。

// 抛出异常的函数返回值类型
function error(message: string): never {
    throw new Error(message);
}

// 根本就没有返回的函数的返回值类型
function infiniteLoop(): never {
    while (true) {
    }
}

类型推断

当没有对变量进行类型注解时,且声明变量时同时对变量赋值了,则ts编译器会根据值自动推断变量类型

let uname = 'lemon'
// ts类型推断为 let uname: string
let mySum = function (x: number, y: number): number {
    return x + y;
}
/* ts类型推断为
let mySum: (x: number, y: number) => number
完整写法如下:
let mySum: (x: number, y: number) => number = function (x: number, y: number): number {
    return x + y;
}
*/

类型断言

告诉解析器变量的类型。

  • 类型断言不是类型转换,它只会影响 TypeScript 编译时的类型, 不会真的影响到变量的类型。

语法:

  1. 变量 as 类型
let str: any = "this is a string";
let strLength: number = (str as string).length;
  1. <类型>变量
let str: any = "this is a string"
let strLength: number = (<string>str).length

应用

function introduce (obj: { name: string, gender: 'male' | 'female' }) {
  console.log(obj.name, obj.gender)
}
// 报错写法:
let lemonObj = {
  name: 'lemon',
  gender: 'female' // 此时ts推断gender变量类型为string类型
}
handleRequest(lemonObj) // 所以传参会报错: Type 'string' is not assignable to type '"female" | "male"'.

// 正确写法1:
let lemonObj = {
  name: 'lemon',
  gender: 'female' as 'female' // 断言gender变量类型为'female’
}

// 正确写法2:
let lemonObj = {
  name: 'lemon',
  gender: 'female'
} as const // as const断言将宽泛的数据类型限定为具体的值类型

辛勤的前端园丁,立志于把每个知识点嚼碎了喂你嘴里!

后续文章指引

  1. # 教程3:Typescript的类型别名及接口