Skip to content

说说你对 TypeScript 的理解,与 JavaScript 的区别? ​

TypeScript(简称 TS)是 JavaScript 的超集,它在 JavaScript 的基础上增加了 静态类型检查、接口、泛型等功能,使代码更安全、可维护,并且支持最新的 JavaScript 语法(ESNext)。

简单来说:

  • JavaScript 是 动态类型 语言,运行时才检查类型错误。
  • TypeScript 是 静态类型 语言,在编译阶段就能发现错误,避免运行时报错。

TypeScript 和 JavaScript 的核心区别 ​

对比项JavaScript(JS)TypeScript(TS)
类型系统动态类型(运行时检查)静态类型(编译时检查)
错误检测运行时才会发现错误编译阶段就能发现错误
可读性 & 维护性代码无类型提示,易出错代码有类型约束,维护更方便
面向对象支持基于原型(Prototype)支持接口、泛型、抽象类等
ES6+ 支持需 Babel 转译原生支持 ES6+ 语法
运行方式直接在浏览器/Node.js 运行需要先编译成 JavaScript

总结 ​

  • TypeScript 让 JavaScript 更安全、可维护,减少运行时错误。
  • 缺点:需要编译,学习成本稍高,但大型项目里非常值得用。
  • 适用场景:适用于 前端(React/Vue/Angular) 和 后端(Node.js) 开发,特别是大型团队合作。

大白话:TypeScript = 加了类型系统的 JavaScript,更安全、更强大、更适合大型项目!

TypeScript 的数据类型有哪些? ​

有 number、string、boolean、bigint、symbol、null、undefined、Array、Tuple、Object、Enum、any、unknown、void、never、联合类型、交叉类型、类型别名、类型断言、interface、type

说说对 TypeScript 中命名空间与模块的理解?区别? ​

命名空间 ​

命名空间是一种内部模块,通过 namespace 关键字定义,主要用于在全局作用域下组织代码,避免变量污染。适用于 无需模块化的全局代码组织(如 UMD 库)。

typescript
namespace Utils {
  export function greet(name: string) {
    return `Hello, ${name}!`;
  }
}

// 使用命名空间
console.log(Utils.greet("Alice"));
  • export 关键字必须添加,否则命名空间内的内容对外不可见。
  • 命名空间的使用不需要 import,直接通过 Utils.greet() 访问。

适用场景:

  • 适用于 浏览器环境(传统 JS 没有模块加载器时)。
  • 大型项目的全局工具库(如 Utils、MathHelper)。

模块 ​

TypeScript 的模块是 基于 ES6 模块语法(import/export) 进行组织的,用于 现代前端项目(React、Vue、Node.js 等),需要模块化管理代码,每个 .ts/.tsx 文件默认就是一个模块(如果使用 import/export)。

typescript
// utils.ts
export function greet(name: string) {
  return `Hello, ${name}!`;
}

// main.ts
import { greet } from "./utils";

console.log(greet("Bob"));
  • export 让 greet 在 utils.ts 之外可见,import 用于引入模块。
  • 模块的加载是基于 CommonJS(Node.js)或 ES6 模块系统(ESM),需要 import 导入。

适用场景:

  • 适用于 所有现代 JS/TS 项目,特别是基于 Node.js、Webpack、Vite、Bun 的项目。
  • 推荐使用模块,而不是命名空间,因为 ES6 模块是现代 JavaScript 标准。

总结:现在推荐使用模块而不是命名空间!!!

TypeScript 中的泛型是什么? ​

泛型(Generics) 是 TypeScript 提供的一种 让代码更通用、更灵活的方式,它允许你在编写代码时不预先指定具体的类型,而是在使用时再指定具体的类型。

为什么需要泛型?

  • 复用性:编写可复用的函数、类、接口,而不局限于某种特定类型。
  • 类型安全:比 any 更安全,能够在编译时检查类型,而不会丢失类型信息。
  • 灵活性:让代码适用于不同的数据类型,提高可扩展性。

什么是 TypeScript 的方法重载? ​

方法重载(Function Overloading) 是指同一个函数可以根据不同的参数类型和数量,执行不同的逻辑。

在 TypeScript 中,虽然 JavaScript 不支持真正的函数重载,但 TypeScript 通过函数声明(签名)+ 实现的方式模拟了方法重载。

在 TypeScript 中,方法重载的语法包括:

  1. 多个函数签名(Overload Signatures):定义不同参数组合的函数声明。
  2. 一个具体的函数实现(Implementation):包含具体的逻辑,并兼容所有签名。

示例:同一个 greet 函数可以接收不同的参数类型

typescript
// 1️⃣ 定义多个重载签名
function greet(name: string): string;
function greet(name: string, age: number): string;

// 2️⃣ 实现函数(必须兼容所有重载)
function greet(name: string, age?: number): string {
  if (age !== undefined) {
    return `Hello, ${name}. You are ${age} years old.`;
  }
  return `Hello, ${name}.`;
}

// 3️⃣ 调用
console.log(greet("Alice")); // ✅ "Hello, Alice."
console.log(greet("Bob", 30)); // ✅ "Hello, Bob. You are 30 years old."
// console.log(greet(42));       // ❌ 错误:参数类型不匹配

TypeScript 支持的访问修饰符有哪些? ​

在 TypeScript 中,访问修饰符用于控制类的属性和方法的可见性,防止不必要的外部访问,提升代码的封装性和安全性。

TypeScript 支持的三种访问修饰符:

修饰符作用
public(默认)任何地方都可以访问
private只能在类的内部访问
protected只能在类的内部或子类访问

tsconfig.json 文件有什么作用 ​

tsconfig.json 是 TypeScript 项目的配置文件,用于指定编译选项、文件路径等,控制 TypeScript 代码的编译方式。

  1. 集中管理 TypeScript 编译配置
  2. 提供严格的类型检查
  3. 支持 ES 模块、目标版本、路径别名等
  4. 提高项目可维护性
  5. 支持增量编译、跳过不必要的编译

TypeScript 中的 Delcare 的关键字有什么作用? ​

在 TypeScript 中,declare 关键字用于声明全局变量、模块、函数、类等,但不会在编译后生成 JavaScript 代码。它的主要作用是告诉 TypeScript 这些变量或模块是外部提供的,自己不会实现。


1. declare 的主要用途 ​

用途作用
声明全局变量告诉 TypeScript 某个全局变量已存在,但不提供具体实现
声明全局函数告诉 TypeScript 某个全局函数已存在,但不提供实现
声明模块适用于引入 非 TypeScript 的第三方库(如 .js)
声明类型(类型定义文件)在 *.d.ts 文件中使用 declare 进行类型定义

2. declare 声明全局变量 ​

如果你在 JavaScript 代码中引入了一个没有 TypeScript 类型定义的全局变量(比如来自 CDN),TypeScript 默认会报错:

js
console.log(window.globalVar); // globalVar 是一个在 JS 里定义的全局变量

TypeScript 会提示:

Cannot find name 'globalVar'.

✅ 使用 declare 解决 ​

在 .d.ts 文件或 ts 文件中:

typescript
declare var globalVar: string;
console.log(globalVar); // ✅ 不会报错

declare 只是声明,不生成 JavaScript 代码。


3. declare 声明全局函数 ​

假设你使用一个全局函数,但 TypeScript 不认识它:

typescript
externalFunction(); // ❌ 报错:Cannot find name 'externalFunction'

✅ 使用 declare 解决 ​

typescript
declare function externalFunction(): void;
externalFunction(); // ✅ 不报错

4. declare 声明全局对象 ​

如果有一个全局对象,包含多个属性:

typescript
declare const API: {
  baseUrl: string;
  version: number;
};

console.log(API.baseUrl);

这样 TypeScript 知道 API 存在,并能提供类型提示。


5. declare 声明模块 ​

如果我们使用 import 导入一个没有 TypeScript 类型的 JavaScript 模块:

typescript
import { someFunction } from "myLibrary";

如果 myLibrary 没有 .d.ts 类型定义文件,TypeScript 会报错:

Cannot find module 'myLibrary'.

✅ 使用 declare module 解决 ​

在 myLibrary.d.ts 中:

typescript
declare module "myLibrary" {
  export function someFunction(): void;
}

这样就可以正常使用 import 了。


6. declare 在 *.d.ts 类型定义文件中 ​

通常,declare 关键字用于 .d.ts(声明文件),帮助 TypeScript 识别外部库的类型。

例如:

typescript
// typings.d.ts
declare module "moment" {
  export function format(date: string): string;
}

这样,在 TypeScript 代码中:

typescript
import { format } from "moment";
format("2025-03-13");

不会报错。


7. declare VS export ​

如果你想要真正定义一个变量、函数或类,需要使用 export 而不是 declare:

关键字作用
declare只是声明,不会编译成 JS 代码
export真实导出,编译后仍然存在
typescript
declare var a: number; // 只告诉 TS "a 存在"
export const b = 10; // 真实存在于编译后的 JS 代码中

8. 总结 ​

✅ declare 关键字用于:

  1. 声明全局变量(declare var / declare let / declare const)
  2. 声明全局函数(declare function)
  3. 声明模块(declare module)
  4. 用于 .d.ts 类型定义文件
  5. 不会在编译后生成 JavaScript 代码

TypeScript 的映射文件是什么? ​

TypeScript 的映射文件(Source Map,.map 文件)是一种调试工具,用于将编译后的 JavaScript 代码映射回 TypeScript 源代码,方便在浏览器开发工具中调试。

什么是类型断言 ​

类型断言允许程序员手动指定一个值的类型。这在需要明确告诉编译器某个值的类型时非常有用。

typescript
let someValue: any = "this is a string";
let strLength: number = (someValue as string).length;

类型守卫(Type Guards)是什么 ​

类型守卫是一种用于在运行时检查类型的技术,它允许开发人员在特定的作用域内缩小变量的范围,以确保正确推断类型。

typescript
function isString(test: any): test is string {
  return typeof test === "string";
}
if (isString(input)) {
  // input 在此代码块中被收窄为 string 类型
}

什么是联合类型和交叉类型 ​

联合类型表示一个值可以是多种类型中的一种,而交叉类型表示一个新类型,它包含了多个类型的特性。

  • 联合类型示例:
typescript
let myVar: string | number;
myVar = "Hello"; // 合法
myVar = 123; // 合法
  • 交叉类型示例:
typescript
interface A {
  a(): void;
}
interface B {
  b(): void;
}
type C = A & B; // 表示同时具备 A 和 B 的特性

什么是 TypeScript 中的声明文件 ​

声明文件(通常以 .d.ts 扩展名结尾)用于描述已有 JavaScript 代码库的类型信息。它们提供了类型定义和元数据,以便在 TypeScript 项目中使用这些库时获得智能感知和类型安全。

keyof 和 typeof 关键字的作用? ​

  • keyof 索引类型查询操作符 获取索引类型的属性名,构成联合类型。
  • typeof 获取一个变量或对象的类型。

简述工具类型 Exclude、Omit、Merge、Intersection、Overwrite 的作用。 ​

  • Exclude<T, U> 从 T 中排除出可分配给 U 的元素。
  • Omit<T, K> 的作用是忽略 T 中的某些属性。
  • Merge<O1, O2> 是将两个对象的属性合并。
  • Compute<A & B> 是将交叉类型合并
  • Intersection<T, U>的作用是取 T 的属性,此属性同样也存在与 U。
  • Overwrite<T, U> 是用 U 的属性覆盖 T 的相同属性。

TypeScript 中 ?.、??、!、!.、_、** 等符号的含义? ​

  • ?. 可选链 遇到 null 和 undefined 可以立即停止表达式的运行。
  • ?? 空值合并运算符 当左侧操作数为 null 或 undefined 时,其返回右侧的操作数,否则返回左侧的操作数。
  • ! 非空断言运算符 x! 将从 x 值域中排除 null 和 undefined
  • !. 在变量名后添加,可以断言排除undefined和null类型
  • _ 数字分割符 分隔符不会改变数值字面量的值,使人更容易读懂数字 .e.g 1_101_324。
  • ** 求幂