Skip to content

TypeScript ​

一、interface 和 type 的区别 ​

两者都能用来定义对象类型,但用途和限制不同。

对比项interfacetype
定义对象✅✅
定义联合类型❌✅
定义元组❌✅
定义原始类型别名❌✅
声明合并✅ 可以❌ 不能
继承/扩展extends&(交叉类型)
实现(implements)✅ 类可以实现⚠️ 只能被类实现,但写法不推荐

举例:

ts
// interface 可以声明合并
interface User { name: string }
interface User { age: number }
// 合并成 { name: string; age: number }

// type 不能
type User = { name: string }
type User = { age: number } // 报错:重复标识符

什么时候用哪个:

  • 定义对象结构、需要继承、需要声明合并 → interface
  • 定义联合类型、元组、函数类型、原始类型别名 → type

二、any / unknown / never ​

类型含义能赋值给谁谁能赋值给它
any任意类型,关闭类型检查任何类型任何类型
unknown未知类型,安全版 any只能赋给 any / unknown任何类型
never永不存在的值任何类型没有任何类型

any ​

ts
let a: any = 1
a = 'str'      // ✅
a.foo.bar      // ✅ 不报错,但运行时可能崩

问题:完全放弃类型检查,容易出 bug。

unknown ​

ts
let u: unknown = 1
u = 'str'          // ✅ 可以赋值
u.foo              // ❌ 报错,必须先收窄类型

if (typeof u === 'string') {
  u.toUpperCase()  // ✅ 收窄后可以用
}

特点:能存任何值,但用之前必须先判断类型。比 any 安全。

never ​

ts
function error(msg: string): never {
  throw new Error(msg)
}

function infiniteLoop(): never {
  while (true) {}
}

特点:表示函数永远不会正常返回(抛错或死循环)。它没有任何值,所以不能被赋值。

关系图 ​

any      ← 最宽松,放弃检查
unknown  ← 中间,安全但需要收窄
never    ← 最严格,没有任何值

优先级:能用 unknown 别用 any;never 用于“不可能发生”的场景。


三、泛型是什么 ​

泛型 = 类型参数化,让一个函数/类/接口能适配多种类型,同时保留类型检查。

不用泛型的问题 ​

ts
function identity(arg: any): any {
  return arg
}
const a = identity('hello') // a 是 any,丢失了类型

用泛型 ​

ts
function identity<T>(arg: T): T {
  return arg
}
const a = identity('hello') // a 是 string,类型保留
const b = identity(123)     // b 是 number

<T> 就是类型参数,调用时自动推断。

常见用法 ​

ts
// 接口
interface Box<T> {
  value: T
}

// 类
class Stack<T> {
  private items: T[] = []
  push(item: T) { this.items.push(item) }
}

// 约束
function getLength<T extends { length: number }>(arg: T): number {
  return arg.length
}

一句话 ​

泛型 = 类型的“变量”,让代码在保持类型安全的同时能复用。


四、extends 做什么 ​

extends 在 TypeScript 里有 3 种用途:

1. 接口继承 ​

ts
interface Animal {
  name: string
}

interface Dog extends Animal {
  bark(): void
}
// Dog 有 name 和 bark

2. 类继承 ​

ts
class Animal {
  move() {}
}

class Dog extends Animal {
  bark() {}
}
// Dog 继承 Animal 的 move

3. 泛型约束 ​

ts
function getLength<T extends { length: number }>(arg: T): number {
  return arg.length
}

含义:T 必须是有 length 属性的类型。这就是给泛型加约束。

ts
getLength('abc')   // ✅ 字符串有 length
getLength([1, 2])  // ✅ 数组有 length
getLength(123)     // ❌ 数字没有 length,报错

条件类型里的 extends ​

ts
type IsString<T> = T extends string ? 'yes' : 'no'

type A = IsString<string>  // 'yes'
type B = IsString<number>  // 'no'

这里的 extends 是条件判断:T 是不是 string 的子类型。


一句话总结 ​

概念核心
interface vs typeinterface 能声明合并,type 更灵活(联合/元组)
any / unknown / neverany 放弃检查,unknown 安全,never 无值
泛型类型参数化,复用 + 类型安全
extends继承(接口/类)、泛型约束、条件类型判断

Code. Log. Share.