06. TypeScript基础:类型系统入门

TypeScript 基础:类型系统入门

TypeScript

JavaScript 是动态类型语言,变量类型在运行时才确定。这带来了灵活性,但也导致了很多运行时错误。TypeScript 给 JavaScript 加上了静态类型系统,让错误在编译时就能被发现。

这一期,我们学习 TypeScript 的基础类型系统。

为什么需要 TypeScript

JavaScript 的痛点

// 这段代码在 JavaScript 中完全合法
let name = "Alice"
name = 123  // 没有报错
name.toUpperCase()  // 运行时报错:name.toUpperCase is not a function

TypeScript 的解决方案

let name: string = "Alice"
name = 123  // 编译时报错:Type 'number' is not assignable to type 'string'

TypeScript 的优势

优势 说明
类型安全 编译时发现错误
智能提示 IDE 自动补全
代码文档 类型即文档
重构友好 改代码有信心

安装 TypeScript

全局安装

npm install -g typescript

项目安装

npm install typescript --save-dev

初始化配置

npx tsc --init

这会生成 tsconfig.json 文件。

基础类型

布尔值

let isDone: boolean = false

数字

let decimal: number = 6
let hex: number = 0xf00d
let binary: number = 0b1010
let octal: number = 0o744

字符串

let color: string = "blue"
color = 'red'
color = <code>green

数组

// 方式1:元素类型后面接 []
let list1: number[] = [1, 2, 3]

// 方式2:使用数组泛型
let list2: Array = [1, 2, 3]

元组

元组表示已知元素数量和类型的数组。

let tuple: [string, number]

tuple = ["hello", 10]  // OK
tuple = [10, "hello"]  // Error

访问元素:

console.log(tuple[0].substring(1))  // OK
console.log(tuple[1].substring(1))  // Error, number 没有 substring

枚举

enum Color {
  Red,
  Green,
  Blue
}

let c: Color = Color.Green
console.log(c)  // 1

自定义值:

enum Color {
  Red = 1,
  Green = 2,
  Blue = 4
}

let c: Color = Color.Green

反向映射:

enum Color {
  Red = 1,
  Green,
  Blue
}

let colorName: string = Color[2]
console.log(colorName)  // 'Green'

any

任意类型,放弃类型检查。

let notSure: any = 4
notSure = "maybe a string"
notSure = false

注意:尽量少用 any,否则就失去了 TypeScript 的意义。

unknown

类型安全的 any。

let notSure: unknown = 4

// 必须类型检查后才能使用
if (typeof notSure === "number") {
  console.log(notSure.toFixed(2))
}

void

没有任何类型,通常用于函数返回值。

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

null 和 undefined

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

默认情况下 nullundefined 是所有类型的子类型。

never

永不存在的值的类型。

// 抛出异常的函数
function error(message: string): never {
  throw new Error(message)
}

// 无限循环
function infiniteLoop(): never {
  while (true) {}
}

object

非原始类型。

declare function create(o: object | null): void

create({ prop: 0 })  // OK
create(null)         // OK
create(42)           // Error
create("string")     // Error

类型断言

告诉 TypeScript "我知道这个类型"。

尖括号语法

let someValue: any = "this is a string"

let strLength: number = (someValue).length

as 语法(推荐)

let someValue: any = "this is a string"

let strLength: number = (someValue as string).length

类型推断

TypeScript 会自动推断类型。

let x = 3  // 推断为 number
let y = "hello"  // 推断为 string

// 从右向左推断
let z = x + 1  // number

联合类型

表示可以是多种类型之一。

let id: string | number

id = "abc123"  // OK
id = 123       // OK
id = false     // Error

实际应用:

function formatValue(value: string | number) {
  if (typeof value === "string") {
    return value.toUpperCase()
  } else {
    return value.toFixed(2)
  }
}

字面量类型

精确到具体的值。

let x: "hello"
x = "hello"  // OK
x = "world"  // Error

联合字面量:

type Direction = "up" | "down" | "left" | "right"

function move(dir: Direction) {
  // ...
}

move("up")     // OK
move("north")  // Error

类型别名

给类型起个名字。

type Name = string
type NameResolver = () => string
type NameOrResolver = Name | NameResolver

function getName(n: NameOrResolver): Name {
  if (typeof n === "string") {
    return n
  } else {
    return n()
  }
}

实践建议

1. 避免使用 any

// Bad
let data: any = fetchData()

// Good
interface User {
  id: number
  name: string
}

let data: User = fetchData()

2. 使用类型推断

// Bad
let x: number = 10

// Good(让 TS 推断)
let x = 10

3. 优先使用 interface

// Bad
type User = {
  name: string
}

// Good(interface 可扩展)
interface User {
  name: string
}

4. 使用严格模式

tsconfig.json 中启用:

{
  "compilerOptions": {
    "strict": true,
    "noImplicitAny": true,
    "strictNullChecks": true
  }
}

总结

TypeScript 的基础类型系统包括:

  • 原始类型:boolean, number, string
  • 复合类型:array, tuple, enum
  • 特殊类型:any, unknown, void, never
  • 类型操作:联合类型、类型断言、类型推断

掌握了这些,你已经可以用 TypeScript 写代码了。下一期,我们学习接口、泛型和高级类型。


学习资源

Views: 0