基础类型与变量声明
2026/7/9大约 4 分钟
基础类型与变量声明
概述
本文面向有 Go 经验的开发者,系统介绍 TypeScript 的基础类型系统和变量声明方式。Go 与 TypeScript 都是静态类型语言,但二者的类型哲学存在显著差异:Go 偏向隐式结构化类型(Structural Typing),TypeScript 则是显式结构化类型,并且在类型表达力上更接近函数式语言。
Go 开发者已知
在 Go 中,基础类型系统较为简洁:
// 基础类型
var a int = 42
var b float64 = 3.14
var c string = "hello"
var d bool = true
// 短变量声明(函数内)
e := "inferred"
// 零值初始化
var f int // 0
var g string // ""
var h bool // false
// 空接口(类似 any)
var i interface{}
i = 42
i = "string"
i = struct{}{}Go 的类型系统核心特点:
- 强类型,但不支持联合类型
interface{}可接受任意类型,但丢失了类型信息- 没有
null的概念(指针为nil) - 不支持字面量类型
TypeScript 怎么做
基础类型注解
// 基础类型
let a: number = 42
let b: string = 'hello'
let c: boolean = true
// 类型推断(推荐)
let d = 42 // 推断为 number
let e = 'hello' // 推断为 string
// null 与 undefined
let f: null = null
let g: undefined = undefined
// bigint
let h: bigint = 9007199254740991n
// symbol
let i: symbol = Symbol('unique')联合类型
// 联合类型:Go 无法直接表达
let id: string | number
id = 'abc123' // OK
id = 42 // OK
// id = true // Error
// 字面量联合类型
type Status = 'active' | 'inactive' | 'pending'
let status: Status = 'active'any vs unknown vs never vs void
// any —— 逃逸类型检查(应避免)
let x: any = 42
x = 'string' // OK
x.toUpperCase() // OK,但运行时可能炸
// unknown —— 安全的 any
let y: unknown = 42
y = 'string' // OK
// y.toUpperCase() // Error: Object is of type 'unknown'
if (typeof y === 'string') {
y.toUpperCase() // OK,类型收窄后
}
// void —— 没有返回值
function log(msg: string): void {
console.log(msg)
}
// never —— 永远不会返回
function throwError(msg: string): never {
throw new Error(msg)
}
// 穷举检查
type Shape = 'circle' | 'square'
function area(shape: Shape): number {
switch (shape) {
case 'circle': return 1
case 'square': return 2
default: {
// shape 被收窄为 never
const _exhaustive: never = shape
return _exhaustive
}
}
}const / let / var
const MAX_SIZE = 100 // 常量,不可重新赋值
let count = 0 // 可变变量,块级作用域
var name = 'old' // 函数级作用域(不推荐)避免使用 var
var 存在变量提升(hoisting)和函数级作用域问题,在现代 TypeScript 中应始终使用 const 或 let。
// var 的怪异行为
console.log(foo) // undefined(不会报错!)
var foo = 1而 let 和 const 存在暂时性死区(TDZ),在声明前访问会抛出错误。
差异分析
| 维度 | Go | TypeScript |
|---|---|---|
| 类型推断 | 有限,依赖 := | 强劲,几乎所有场景可推断 |
| 联合类型 | 不支持 | 一等公民 string | number |
| 空值 | nil 与零值 | null / undefined 分离 |
| 字面量类型 | 不支持 | type Day = 1 | 2 | 3 |
| 空接口 vs any | interface{} 需类型断言 | any 彻底逃逸检查 |
| 零值 | 自动零值初始化 | 无零值,必须显式赋值 |
结构化类型(Structural Typing)
Go 和 TypeScript 都采用结构化类型系统(鸭子类型),但 Go 的结构化发生在隐式实现接口时,而 TypeScript 的结构化发生在编译期类型兼容性检查中。
// TypeScript 结构化类型
interface Point {
x: number
y: number
}
const p = { x: 1, y: 2 } // 自动兼容 Point
const q = { x: 1, y: 2, z: 3 } // 额外属性也兼容Bad Practice
// Bad: 滥用 any 逃逸类型安全
function process(data: any) {
return data.name.toUpperCase() // 运行时可能崩溃
}
// Bad: 使用空对象类型 {} 而非 Record
function validate(obj: {}) {} // 可接收任何非 null/undefined 值
// Bad: 忽略 strictNullChecks
// tsconfig.json 中未开启 strictNullChecks
function getName(user: { name: string | null }) {
return user.name.toUpperCase() // 运行时崩溃
}
// Bad: over-annotation 过度注解
const name: string = 'hello' // 多余,TS 能推断
const items: Array<number> = [1, 2, 3] // 多余Best Practice
// Good: 优先 unknown 而非 any
function safeProcess(data: unknown) {
if (typeof data === 'object' && data !== null && 'name' in data) {
return (data as { name: string }).name.toUpperCase()
}
throw new Error('Invalid data')
}
// Good: 开启 strictNullChecks
// tsconfig.json: "strictNullChecks": true
function getName(user: { name: string | null }): string {
return user.name?.toUpperCase() ?? 'UNKNOWN'
}
// Good: 利用联合类型精确表达
type Result<T> =
| { status: 'success'; data: T }
| { status: 'error'; message: string }
// Good: 让类型推断工作
const items = [1, 2, 3] // number[]
const config = { host: 'local', port: 8080 } // { host: string; port: number }
// Good: 使用字面量类型枚举值
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE'
// Good: 穷举检查确保安全
type Color = 'red' | 'green' | 'blue'
function getHex(c: Color): string {
const map: Record<Color, string> = {
red: '#FF0000',
green: '#00FF00',
blue: '#0000FF',
}
return map[c]
}开启 strict 模式
在 tsconfig.json 中开启 strict: true 可获得完整的类型安全保护,包括 strictNullChecks、noImplicitAny、strictFunctionTypes 等关键检查。
{
"compilerOptions": {
"strict": true
}
}总结
TypeScript 的类型系统比 Go 更加丰富和灵活。作为 Go 开发者,你需要适应的是:
- 联合类型 —— 用类型描述值域,而非运行时检查
null/undefined分离 —— 显式声明可空性unknown优先于any—— 保持类型安全的最后防线- 放弃
var—— 拥抱const和let
下一章将介绍 接口与类型别名,这是 TypeScript 类型系统的核心构造。