Skip to content

TypeScript 基础知识

  • TypeScript(简称 TS)是微软公司开发的一种基于 JavaScript (简称 JS)语言的编程语言。

  • TypeScript 可以看成是 JavaScript 的超集(superset),即它继承了后者的全部语法,所有 JavaScript 脚本都可以当作 TypeScript 脚本(但是可能会报错),此外它再增加了一些自己的语法。

  • TypeScript 对 JavaScript 添加的最主要部分,就是一个独立的类型系统。

基本类型

TypeScript 继承了 JavaScript 的类型设计

原始类型

boolean

boolean 类型只包含 truefalse

ts
const x: boolean = true
const y: boolean = false

string

ts
const name: string = 'Aximy'
const hello: string = `hello ${name}`

number

number 类型包含所有整数和浮点数。

ts
const x: number = 111
const y: number = 1.23
const z: number = 0xffff

bigint

bigint 类型包含所有大整数,与 number 类型不兼容。

ts
const x: bigint = 1000n;
const y: bigint = 0xffffn;

TIP

注意,bigint 类型是 ES2020 标准引入的。如果使用这个类型,TypeScript 编译的目标 JavaScript 版本不能低于 ES2020(即编译参数target不低于es2020)。

symbol

symbol 类型代表独一无二的值,使用构造函数创建。

ts
const x: symbol = Symbol('Aximy')

object

object 类型包含了对象、数组和函数

ts
const obj: object = { foo: 123 }
const arr: object = [1, 2, 3]
const func: object = (n: number) => n + 1

undefined 和 null

这两种类型是独立的类型,各自只有一个值。

ts
const x: undefined = undefined; // 未定义

const y: null = null; // 空

在关闭编译设置 noImplicitAnystrictNullChecks 时,它们的类型会被推断为 any

特殊类型

any

any 类型表示没有限制,可以赋予任意类型的值。

ts
let x: any = 0
x = 'hello'
x = true

适用场景:需要关闭变量的类型检查时

WARNING

不宜使用 any 的主要原因之一:污染其它变量,运行时报错

ts
let x: any = 'hello'
let y: number

y = x // 编译不报错

y * 123 // 编译不报错
y.toFixed() // 编译不报错

unknown

为了解决 any 污染问题,TypeScript 3.0 引入了 unknown 类型。

可以看作严格版的 any 类型,相似之处是可以分配任意类型,不同之处在于:unknown 类型不能直接使用

ts
let v: unknown = 123;

let v1: boolean = v // 报错
let v2: number = v // 报错

需要“类型缩小”后使用:

ts
let v: unknown = 123

if (typeof v === 'boolean') {
  let v1: boolean = v // 正确
} else if (typeof v === 'number') {
  let v2: number = v // 正确
}

never

never 类型表示不存在的值的类型,常用于一个从来不会有返回值的函数,或者一个总是会抛出错误的函数。

ts
// 不会有返回值
function infiniteLoop(): never {
  while (true) {}
}

// 总是会抛出错误的函数
function error(message: string): never {
  throw new Error(message)
}

数组

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

ts
/* 示例:声明 number 类型数组 */
// 方式一:
const arr: number[] = [1, 2, 3]

// 方式二:
const arr: Array<number> = [1, 2, 3]

元组 Tuple

元组(Tuple)是 TypeScript 特有的数据类型,用来表示“成员类型可以自由设置的数组”

ts
const user: [string, number] = ['Aximy', 1]

// 可选成员,可选成员必须在必选成员之后
const a: [number, number?] = [1]

// 不定数量的成员
const b: [number, ...string[]] = [0, '1', '1']

// 不确定元组成员的类型和数量
type Tuple = [...any[]]

枚举 Enum

TypeScript 中引入了 enum 类型,是对 JavaScript 标准数据类型的补充

ts
enum Color {
  Red,
  Green,
  Blue,
}
const green: Color = Color.Green
  • 都没有初始值时,默认从 0 开始递增
  • 如果只设定第一个成员的值,后面成员的值就会从该值递增
  • 成员的值可以是任意数值,但不能是 bigint

type 类型别名

type 关键字用来定义类型别名,主要用来定义一些复杂类型,还可以增加代码的可读性。

ts
type Name = string

const name: Name = 'Aximy'

字面量类型

字面量类型是以单个值作为类型。

ts
// 字符串字面量类型
type Name = 'Aximy' | 'Xmy' | 'Yang'

// 数字字面量类型
type Age = 18 | 19 | 20

// 布尔字面量类型
type isFlag = true

联合类型

联合类型由多个类型组成,使用 | 符号连接,表示值为其中的一种

ts
let x: string | number
x = 123
x = 'a'

WARNING

读取变量时,除非访问公有的成员。先区分类型再处理,否则编译报错

ts
function getLength(value: string | number): number {
  // Error: 类型 “string | number” 上不存在属性 “length”(类型 “number”上 不存在属性 “length”)
  return value.length
}

交叉类型

交叉类型由多个类型组成,使用 & 符号连接,表示必须同时符合这些类型

ts
let obj: { foo: string } & { bar: string }

obj = {
  foo: 'hello',
  bar: 'world'
}

函数

对函数进行类型约束时,需要指定函数的参数类型和返回类型。

ts
// 函数声明
function add(x: number, y: number): number {
  return x + y
}

// 函数表达式
const add: (x: number, y: number) => number = function (x, y) {
  return x + y
}

// 箭头函数
const add = (x: number, y: number): number => x + y

可选参数

使用 ? 表示可选参数,注意:可选参数必须在必选参数后边!

ts
const add = (x: number, y?: number): void => console.log(x + y)

参数默认值

ES6 允许参数设置默认值,在 TS 中有默认值的参数就是可选的,但是参数位置不受限制。

ts
function add(x: number = 10, y: number): number {
  return x + y
}

add(20, 20) // 40
/* 必须显示传递一个 undefined 进行占位 */
add(undefined, 10) // 20

rest 剩余参数

ES6 使用 ...变量名 的方式获取函数的剩余参数

ts
getTotal(1, 2, 3, 4)

function getTotal(a: number, ...rest: number[]) {
  console.log(a) // 1
  console.log(rest) // [2, 3, 4]
}

对象类型 — 接口

使用接口(interface)定义对象的类型,接口对类型做出了限制,并不会编译到 JS 中

TIP

对象的属性必须与接口中规定的一致,否则编译出错

ts
interface User {
  name: string
  age: number
}

const user: User = {
  name: 'Aximy',
  age: 0
}

可选属性

使用 ? 符号标记可选属性。意味着该属性可以不存在。

ts
interface User {
  name: string
  age?: number
}

const user: User = {
  name: 'Aximy'
}

只读属性

使用 readonly 关键字,表示属性为只读属性,不能更改。

ts
interface User {
  readonly name: string
  age?: number
}

如果对象属性只读的话,不能替换掉整个对象,修改对象的属性是可以的。

任意属性

使用 []:类型 方式允许接口中有任意的属性

ts
interface User {
  name: string
  [propName: string]: any
}

const user: User = {
  name: 'Aximy',
  age: 0
}

WARNING

如果定义了任意属性,确定属性以及可选属性的类型必须是任意类型的子集

ts
interface User {
  name: string
  [propName: string]: string
}

const user: User = {
  name: 'Aximy',
  age: 0 // Error: 属性 "age"与索引签名不兼容,不能将 "number" 分配给类型 "string"
}

使用联合类型即可解决 👇

ts
interface User {
  name: string
  [propName: string]: string | number
}

如有转载请标注本站地址