⚠️温馨提示: 文档中包含【2个】暂不支持的区域,请通过搜索关键字【暂不支持的文档区域】进行后续处理

typescript-notes.zip

很多同学可能第一次来,我之前分享了很多公开课,希望对你的技术成长有帮助!

免费分享都在这里,需要 文档和配套视频回放找咨询老师 领取~

【飞书文档】Docker 入门与服务编排进阶,字节前端专家带你光速掌握 CI/CD 运维技能


【飞书文档】ESLint 前端编码规范化与原理剖析,特邀字节大佬分享团队代码质量把控细节

【飞书文档】Notion 与飞书文档协同方案精析,字节前端专家传授百万年薪架构师级项目重难点 飞书文档编辑器原理续,进阶

【飞书文档】Ant Design 组件库架构设计与开发实践,高级前端专家带你掌握基建面试技巧 组件库与团队基建面试必看

【飞书文档】Taro、Tauri 多端开发实践与原理剖析,《Taro 多端开发权威指南》作者带你悟透多端框架原理 多端开发涨薪必学


【飞书文档】Nest 服务端开发与原理深度剖析,《NestJS 实战》作者带你领略框架设计之美 全栈进阶,企业级框架

【飞书文档】Babel 与编译原理详解,字节高级前端专家带你从零实现飞书表格公式执行器

【飞书文档】服务端渲染(SSR)与前后端同构技术原理揭秘,字节前端专家带你光速进阶全栈 进阶必学


【飞书文档】大数据可视化引擎与数字孪生平台设计浅析,字节架构师:一起来剖析 DataWind 数据洞察平台架构之道

【飞书文档】飞书文档协同编辑器技术揭秘,特邀字节架构师分享富文本编辑器方案细节

【飞书文档】前端性能与异常监控平台全链路设计与实践,字节架构师:掌握这整套拿个 40K+ 不在话下吧

【飞书文档】字节面试专场——中厂在职学员冲击大厂 30K+,看看面试官如何评价 大厂模拟面试,问得很深慎看

【飞书文档】冲击中大厂筹备与涨薪突击最优方案,特邀字节面试官带你体验大厂面试全流程


【飞书文档】Webpack 原理深度解读与面试专项突击,字节面试官带你手撕难缠打包构建面试原理题 工程化与构建原理深入

【飞书文档】脚手架/CLI 工具原理与开发实践,特邀字节前端专家带你体悟大厂团队基建与研发工作流 团队基建必看

【飞书文档】Vite 构建过程与源码深度剖析,你怎么也想不到一线大厂工程化构建面试会问这么深!

【飞书文档】Vue3 源码深度剖析,字节面试官教你轻松拿捏高级前端专家面试框架原理题

【飞书文档】React18 源码深度剖析,字节面试官教你轻松拿捏高级前端专家面试框架原理题

【飞书文档】前端破局 AI 应用开发,特邀字节大佬分享字节系 AI 场景落地应用与 AI 引擎编排流程 探索前端新方向同学福音


【飞书文档】高级前端专家如何做性能优化?特邀字节大佬细数飞书应用优化细节(二)【内部培训版】

【飞书文档】小小微前端,轻松拿捏,特邀字节大佬开讲微前端架构与源码剖析【内部培训版】 35K+ 同学必看

【飞书文档】高级前端专家如何做项目架构与工程化设计? 特邀字节大佬细数字节开源项目架构细节【超详细内培版】

【飞书文档】高级前端专家如何做性能优化?特邀字节大佬细数飞书应用优化细节【超详细内培版】


【飞书文档】面试被算法干吐了?字节大佬带你突破极限,冲击 30K+ 必掌握算法与 WebAssembly 技术 冲刺年包 50W+ 同学必看

【飞书文档】字节大佬带你弯道超车,深入剖析大厂面试真题~

【飞书文档】项目没有难点亮点?字节大佬带你前端项目弯道超车

【飞书文档】备战金九银十,进阶大前端,涨薪全突破! 跳槽涨薪需求同学必看

  • 初中级 】请说说在你参与的项目中,常用的 Typescript 用法与特性
  • 中高级 】在项目构建与初始化初期,你是怎样考虑 Typescript 编译方案与打包工具选择
  • 专家级 】你作为前端 Leader,说说过往项目设计时调研的热门优秀开源项目,并说说你认为的 Typescript 最佳实践

附:Typescript 学习最短路径图

⚠️ 暂不支持的文档区域,【文档小组件】

初中级 】请说说在你参与的项目中,常用的 Typescript 用法与特性

在我参与的项目中,TypeScript 是非常重要的一环,帮助提升了代码的可维护性、可靠性和开发效率。TypeScript 提供了强大的类型系统和多种特性,以下是一些我在项目中常用的 TypeScript 用法和特性,包括基础类型、接口( interface )、类型别名( type alias )、泛型( generics )和类型推导( type inference )。

基础类型(Basic Types)

TypeScript 提供了一些基本类型来确保变量、函数参数和返回值的类型一致,从而帮助开发者避免一些常见的类型错误。以下是一些常用的基础类型:

  • 布尔值(boolean) : 用于表示 truefalse
let isActive: boolean = true;
  • 数字(number) : 用于表示整数或浮点数。
let age: number = 30;
  • 字符串(string) : 用于表示文本数据。
let name: string = "Alice";
  • 数组(Array) : TypeScript 提供了两种方式来声明数组类型。
let numbers: number[] = [1, 2, 3];
// 或者
let strings: Array<string> = ["apple", "banana", "cherry"];
  • 元组(Tuple) : 元组是固定长度的数组,可以包含不同类型的元素。
let person: [string, number] = ["Alice", 30];
  • 枚举(Enum) : 枚举是 TypeScript 中的一种特殊类型,用于表示一组命名常数。
enum Color {
  Red = 1,
  Green,
  Blue
}
let color: Color = Color.Green;
  • 任意类型(any) : 允许任何类型的值,类似于 JavaScript 的动态类型。
let data: any = 42;
data = "Hello";
data = true;
  • 空值(void) : 用于函数没有返回值时指定其返回类型。
function log(message: string): void {
  console.log(message);
}
  • nullundefined : 这两个类型表示变量没有值。
let nothing: null = null;
let noValue: undefined = undefined;

接口(Interface)

interface 是 TypeScript 中用于定义对象结构的关键特性之一。它可以指定对象的属性、方法及其类型,且可以通过扩展实现复用。

  • 定义基本接口 :
interface Person {
  name: string;
  age: number;
}
let user: Person = {
  name: "Alice",
  age: 30
};
  • 可选属性 : 使用 ? 来定义可选属性。
interface Person {
  name: string;
  age?: number;  // 可选属性
}
let user1: Person = { name: "Alice" };
  • 只读属性 : 使用 readonly 来定义只读属性,确保它们不能被修改。
interface Point {
  readonly x: number;
  readonly y: number;
}
const point: Point = { x: 10, y: 20 };
// point.x = 5; // 错误,x 是只读的
  • 函数类型 : 可以通过接口来定义函数的类型。
interface Greet {
  (name: string): string;
}
const greet: Greet = (name) => `Hello, ${name}`;
  • 接口扩展 : 接口支持继承,可以扩展其他接口。
interface Animal {
  name: string;
}
interface Dog extends Animal {
  breed: string;
}
let dog: Dog = { name: "Buddy", breed: "Golden Retriever" };

类型别名(Type Alias)

type 关键字可以用于定义类型别名,它可以给任何类型起一个名字,可以是基础类型、联合类型、交叉类型等。

  • 基础类型别名 :
type StringOrNumber = string | number;
let value: StringOrNumber = "Hello";
value = 42;
  • 联合类型 : 使用 | 来表示多个类型的联合。
type Status = "success" | "error" | "loading";
let currentStatus: Status = "success";
  • 交叉类型 : 使用 & 来合并多个类型。
type Person = { name: string; age: number };
type Employee = { company: string };
type Worker = Person & Employee;
const worker: Worker = { name: "Alice", age: 30, company: "TechCo" };
  • 字面量类型 : 可以指定具体的值类型。
type Direction = "north" | "south" | "east" | "west";
let direction: Direction = "north";

泛型(Generics)

泛型是 TypeScript 中的一个强大特性,它允许你创建可以适用于多种类型的函数、接口或类。泛型能够让类型变得更加灵活和可重用,同时保持类型安全。

  • 泛型函数 : 使用泛型来使函数支持不同类型的输入输出。
function identity<T>(arg: T): T {
  return arg;
}
let result = identity(42);  // T 被推断为 number
let result2 = identity("Hello");  // T 被推断为 string
  • 泛型接口 : 使用泛型接口定义函数类型。
interface IdentityFn<T> {
  (arg: T): T;
}
const identity: IdentityFn<number> = (arg) => arg;
  • 泛型类 : 泛型可以用于类定义,允许类实例的类型在创建时指定。
class Box<T> {
  value: T;
  constructor(value: T) {
    this.value = value;
  }
}
const box = new Box(10);  // T 被推断为 number
  • 泛型约束 : 泛型还可以使用约束来限制它的类型。
function getLength<T extends { length: number }>(arg: T): number {
  return arg.length;
}

类型推导(Type Inference)

TypeScript 在大多数情况下可以自动推导出变量的类型,而不需要显式声明类型。这减少了代码量,提高了开发效率。

  • 基本类型推导 :
let age = 30;  // TypeScript 会推导 age 的类型为 number
let name = "Alice";  // TypeScript 会推导 name 的类型为 string
  • 函数返回值类型推导 : 如果函数返回值没有显式声明,TypeScript 会根据返回值推导出类型。
function add(a: number, b: number) {
  return a + b;  // TypeScript 推导出返回值类型为 number
}
  • 数组和对象的推导 : TypeScript 可以推导数组和对象的类型。
let numbers = [1, 2, 3];  // 推导为 number[]
let person = { name: "Alice", age: 30 };  // 推导为 { name: string; age: number }

extends 关键字

extends 在 TypeScript 中有多个用法,主要有以下几种:

  1. 用于继承类
  2. 用于泛型约束
  3. 用于条件类型的类型推断

用于继承类

在类之间使用 extends 关键字可以继承一个类的所有属性和方法。

class Animal {
  name: string;
  constructor(name: string) {
    this.name = name;
  }
  speak() {
    console.log(`${this.name} makes a sound`);
  }
}

class Dog extends Animal {
  constructor(name: string) {
    super(name);  // 调用父类的构造函数
  }
  speak() {
    console.log(`${this.name} barks`);
  }
}

const dog = new Dog("Buddy");
dog.speak();  // 输出 "Buddy barks"

用于泛型约束

extends 可以用于约束泛型的类型,确保泛型类型满足特定条件。这样可以确保泛型类型的安全性和正确性。

function identity<T extends string | number>(value: T): T {
  return value;
}

let a = identity("Hello");  // a 的类型是 string
let b = identity(42);       // b 的类型是 number
// let c = identity(true);   // 错误:类型 'boolean' 不能赋给类型 'string | number'

在这个例子中, T extends string | number 约束了泛型类型 T 只能是 stringnumber 类型,这避免了不符合条件的类型传入。

用于条件类型

extends 关键字还常常与条件类型结合使用,用来根据类型进行不同的推导或处理。

type IsString<T> = T extends string ? "Yes" : "No";

type Test1 = IsString<string>;  // "Yes"
type Test2 = IsString<number>;  // "No"

在这个例子中, T extends string 用来检查 T 是否为 string 类型。如果是 string ,则类型为 "Yes" ;否则,类型为 "No"

infer 结合使用

extendsinfer 一起使用时,可以在条件类型中提取和推断类型。

type ExtractReturnType<T> = T extends (...args: any[]) => infer R ? R : never;

type Func = (a: number, b: number) => string;
type ReturnTypeOfFunc = ExtractReturnType<Func>;  // ReturnTypeOfFunc 会被推导为 string

在这个例子中, T extends (...args: any[]) => infer R 判断 T 是否是一个函数类型,并使用 infer R 提取函数的返回类型。

条件类型与 extends 的综合应用

你可以通过组合条件类型和 extends 来实现更复杂的类型推导。例如,下面的代码判断一个类型是否是 Function 类型,并返回相应的类型:

type MyType<T> = T extends Function ? "It's a function" : "It's not a function";

type Result1 = MyType<() => void>;   // "It's a function"
type Result2 = MyType<string>;       // "It's not a function"

infer 关键字

infer 是 TypeScript 中的一个高级特性,主要用于条件类型中,可以根据类型推断出一个子类型,并将其赋给一个新的类型变量。 infer 通常与条件类型( extends )结合使用,允许你从某些类型中提取部分信息。

基本语法

type ReturnTypeOf<T> = T extends (...args: any[]) => infer R ? R : never;

在这个例子中, infer R 会自动推断出一个函数返回类型 R 。如果 T 是一个函数类型, R 就是该函数的返回类型;否则返回 never

例子 1:获取函数返回类型

假设你有一个函数,并希望获取其返回值的类型,你可以使用 infer 来实现:

type ReturnTypeOf<T> = T extends (...args: any[]) => infer R ? R : never;

function greet(name: string): string {
  return `Hello, ${name}`;
}

type GreetReturnType = ReturnTypeOf<typeof greet>;  // GreetReturnType 会被推导为 string

这里的 ReturnTypeOf 类型别名使用了 infer R 来提取 greet 函数的返回类型,并将其赋值给 GreetReturnType ,所以 GreetReturnType 的类型是 string

例子 2:从 Promise 中提取类型

你可以使用 infer 来从 Promise 类型中提取 resolve 的类型:

type ResolvedType<T> = T extends Promise<infer R> ? R : T;

type ResolvedString = ResolvedType<Promise<string>>;  // ResolvedString 的类型是 string
type ResolvedNumber = ResolvedType<Promise<number>>;  // ResolvedNumber 的类型是 number

在这个例子中, ResolvedType 使用 infer R 来提取 Promise 中的类型。如果类型是 Promise ,它会提取出 resolve 时的值类型;否则,它会直接返回原始类型。

总结

  1. infer :用于条件类型中,从类型中推断出一个子类型,可以提取出一个类型的部分结构或值类型。它通常和 extends 结合使用,帮助我们在类型推导时提取出一些具体的类型信息。
  2. extends :除了用来继承类外, extends 在泛型和条件类型中也有广泛应用,它用于约束泛型类型、实现条件类型判断或提取类型。通过 extendsinfer 的组合,TypeScript 可以实现更为灵活和强大的类型推导。

这两个关键字是 TypeScript 类型系统的核心,掌握它们能够大大增强你处理复杂类型的能力,提升代码的类型安全性和可维护性。

中高级 】在项目构建与初始化初期,你是怎样考虑 Typescript 编译方案与打包工具选择

在项目的初期阶段,选择合适的 TypeScript 编译方案和打包工具至关重要。这不仅影响开发效率,还能直接影响最终的构建性能、代码质量以及开发者体验。

TypeScript 作为一种静态类型语言,它的编译方式和工具链配置尤为重要。接下来我们将详细介绍从 tscVite ,再到 tsup 的使用场景与配置选择,一起了解如何选择合适的构建工具并配置它们来提高开发体验和构建效率。

tsc (TypeScript Compiler):传统的 TypeScript 编译工具

tsc 是 TypeScript 官方提供的编译工具,用于将 TypeScript 代码编译为 JavaScript。

它是 TypeScript 项目中最基础的工具,提供了非常多的自定义选项,允许我们根据需求配置不同的编译行为。

tsconfig.json 配置详解

tsc 的构建输出由 tsconfig.json 文件配置。 tsconfig.json 是 TypeScript 编译器的配置文件,所有的 TypeScript 编译选项都可以在这个文件中设置。以下是一些常用的配置项及其含义:

基础配置

{
  "compilerOptions": {
    "target": "es5",            // 设置编译后的 JavaScript 版本
    "module": "esnext",         // 设置模块系统(例如:ES6模块、CommonJS)
    "lib": ["dom", "es6"],      // 指定编译时使用的库(默认包括 ES5)
    "sourceMap": true,          // 生成 .map 文件,用于调试
    "strict": true,             // 启用所有严格类型检查选项
    "esModuleInterop": true,    // 使默认导入工作正常(兼容 CommonJS)
    "skipLibCheck": true,       // 跳过库文件的类型检查,加快编译速度
    "forceConsistentCasingInFileNames": true // 确保文件名的大小写一致
  }
}

项目结构配置

{
  "include": ["src/**/*"],   // 指定要编译的文件夹或文件
  "exclude": ["node_modules"], // 排除不需要编译的文件夹
}
  • target : 设置编译后生成的 JavaScript 的目标版本(如 es5es6 等)。在支持现代 JavaScript 的项目中,通常选择 esnext ,这样编译后的代码就会尽可能符合当前的标准。
  • module : 用于指定模块系统(如 CommonJSESNext )。如果你在 Node.js 环境中开发,一般使用 CommonJS ,如果你在前端使用模块化,建议使用 ESNext
  • lib : 配置 TypeScript 编译时可用的库文件。例如, es6 表示支持 ES6 的标准库, dom 表示浏览器相关的 API 库。
  • strict : 开启 TypeScript 的严格模式。它包含了对类型检查的严格要求,例如 noImplicitAnystrictNullChecks 等,强烈建议在项目中启用。
  • sourceMap : 配置是否生成源映射文件( .map 文件),便于调试时追踪 TypeScript 代码。
  • esModuleInterop : 启用后,允许从 CommonJS 模块默认导入。它通常在与老旧 JavaScript 代码兼容时非常有用。

tsc 的优缺点

  • 优点 :

    • 广泛支持 : tsc 是官方提供的 TypeScript 编译工具,支持所有 TypeScript 特性。
    • 配置灵活 : 可以通过 tsconfig.json 文件高度定制。
  • 缺点 :

    • 构建速度较慢 : 相比于现代的构建工具, tsc 在大型项目中的构建速度较慢。
    • 缺乏增量构建支持 : 每次编译都会重新编译整个项目,缺乏快速增量构建的支持。

Vite:现代前端开发的构建工具

Vite 是一个现代化的前端构建工具,它以极快的启动速度和优化的构建流程著称。

Vite 内部使用了 Rollup 作为打包工具,同时它还提供了对 TypeScript 的良好支持,因此在很多项目中,尤其是前端项目中,Vite 已成为首选的构建工具。

为什么选择 Vite?

  • 快速启动 : Vite 通过利用浏览器的原生 ES 模块支持,只在需要时动态构建代码。这比传统的打包工具(如 Webpack)要快得多。
  • 热更新(HMR) : Vite 提供了非常快的模块热更新(Hot Module Replacement),提高了开发时的效率。
  • TypeScript 集成 : Vite 内部已经集成了 TypeScript 支持,无需额外配置。只需在项目中安装 TypeScript,Vite 会自动识别并处理 TypeScript 文件。
  • 现代化配置 : 使用 Vite 时,你只需配置非常少的内容,大多数功能默认开箱即用。例如,Vite 会自动使用 tsconfig.json 中的 TypeScript 配置。

Vite 配置文件示例

// vite.config.ts
import { defineConfig } from 'vite';

export default defineConfig({
  plugins: [],
  server: {
    port: 3000,            // 设置开发服务器的端口
    open: true             // 启动时自动打开浏览器
  },
  build: {
    target: 'esnext',      // 设置编译目标为最新的 ES 版本
    outDir: 'dist',        // 设置输出目录
  },
  resolve: {
    alias: {
      '@': '/src',         // 设置路径别名
    },
  },
});

在 Vite 中,TypeScript 配置会自动从项目的 tsconfig.json 文件中加载,基本上不需要额外配置。如果需要自定义 TypeScript 配置,只需要修改 tsconfig.json 即可。

Vite 的优缺点

  • 优点 :

    • 快速构建 : 使用现代浏览器的模块化特性,构建启动极为迅速。
    • 开箱即用 : Vite 默认支持 TypeScript、JSX、ESM 等,无需复杂的配置。
    • 强大的开发体验 : 支持热更新(HMR),使开发体验更加流畅。
  • 缺点 :

    • 成熟度 : 虽然 Vite 在前端开发中已经非常流行,但它在一些复杂的构建需求(如服务器端渲染、静态站点生成等)下,可能需要更多的配置和插件支持。
    • 插件生态还在完善 : 虽然 Vite 已经拥有很多插件,但在某些特殊场景下,插件的数量和质量可能不如 Webpack。

tsup :简洁高效的 TypeScript 打包工具

对于工具库、UI 库等类型的项目,通常我们会选择 tsup 作为打包工具。 tsup 是一个专注于高效构建 TypeScript 项目的打包工具,它基于 esbuild(一个快速的构建工具)构建,并且提供了简单的配置和高效的构建性能。

为什么选择 tsup

  • 快速构建 : tsup 基于 esbuild,提供极快的构建速度,比传统的 TypeScript 编译工具(如 tsc )要快得多。
  • 简化配置 : tsup 提供了极简的配置方式,尤其适合用于库的构建。它的默认配置已经能满足大多数常见需求。
  • 多格式支持 : tsup 可以输出多种模块格式(如 ESM、CommonJS、UMD),方便库的发布。
  • 内置 TypeScript 支持 : tsup 内置了对 TypeScript 的支持,项目中不需要额外的 TypeScript 配置文件。

tsup 配置文件示例

// tsup.config.ts
import { defineConfig } from 'tsup';

export default defineConfig({
  entry: ['src/index.ts'],
  format: ['esm', 'cjs'],      // 支持 ESM 和 CommonJS 格式
  dts: true,                   // 生成类型声明文件
  sourcemap: true,             // 生成 source map
  clean: true,                 // 清理输出目录
});

tsup 中,配置

相对简单,通常只需要指定入口文件、输出格式、是否生成声明文件等基本设置。得益于 esbuild 的高性能,构建速度非常快,适合用来构建库或者组件。

tsup 的优缺点

  • 优点 :

    • 高效 : 基于 esbuild,构建速度极快。
    • 简洁配置 : 配置文件简洁且功能强大,适合工具库或 UI 库。
    • 多格式支持 : 可以同时输出多种模块格式(ESM、CommonJS、UMD 等)。
  • 缺点 :

    • 较少的配置选项 : 相比 Webpack 和 Vite, tsup 提供的配置选项较少,可能在一些复杂的构建需求中不够灵活。
    • 生态系统较小 : 相较于 Webpack, tsup 的插件生态相对较小,适合小型项目和库的构建。

方案选型对比

在项目构建与初始化的初期,选择合适的 TypeScript 编译与打包工具至关重要:

  1. tsc 是最基础的 TypeScript 编译工具,适用于需要详细定制编译行为的场景,特别适用于较简单的 TypeScript 项目。
  2. Vite 是现代前端项目的理想选择,因其快速的构建性能、开箱即用的 TypeScript 支持和出色的开发体验,非常适合用于前端开发。
  3. tsup 则是库开发和工具项目的理想选择,它提供快速、简洁的 TypeScript 打包方案,特别适合构建工具库、UI 组件库等项目。

根据项目的需求和复杂度选择合适的工具,能够极大地提高开发效率并优化构建流程。

专家级 】你作为前端 Leader,说说过往项目设计时调研的热门优秀开源项目,并说说你认为的 Typescript 最佳实践

作为前端团队的领导者,项目设计不仅仅是技术的选择问题,更是开发流程、团队协作和项目长期可维护性的考虑。近年来,随着 TypeScript 的广泛应用,很多企业级项目和开源项目都逐渐采用了 TypeScript,以增强代码的可维护性和可靠性。

今天,我们一起来看看在设计前端项目时调研的热门开源项目与企业级项目,并结合这些项目中的实践来谈谈 TypeScript 最佳实践。

热门开源项目借鉴

在项目设计中,参考一些优秀的开源项目可以帮助团队少走弯路,借鉴成熟的架构、模式和最佳实践。以下我们将从 Vite、react-hook-form 和 Ant Design 的实际源码出发,围绕 monorepo 架构、TypeScript 配置以及类型定义与推导技巧展开分析。

Vite TypeScript 最佳实践

项目整体 monorepo 架构分析

Vite 项目采用了典型的 monorepo 架构,其源码目录结构如下:

vite/
├── packages/
│   ├── vite/          # 核心包
│   ├── create-app/    # 脚手架工具
│   ├── plugin-*       # 各种插件包
│   └── shared/        # 公共工具包
├── scripts/           # 构建和发布脚本
├── tsconfig.base.json # 共享的 TypeScript 配置
├── package.json       # 根目录依赖管理
└── ...                # 其他配置文件
架构亮点:
  1. 模块化开发 :每个功能模块独立为一个包,便于团队协作。
  2. 共享工具与配置 :公共模块放在 shared ,提高复用性。
  3. 统一管理依赖 :通过根目录的 package.jsonpnpm 实现依赖的统一管理。
  4. 独立构建与测试 :每个子包可以独立构建,使用 tsc -b 批量构建。

TypeScript 配置实践

基础配置(根目录 tsconfig.base.json ):
{
  "compilerOptions": {
    "target": "ESNext",
    "module": "ESNext",
    "strict": true,
    "baseUrl": ".",
    "paths": {
      "@vitejs/*": ["packages/*/src"]
    }
  },
  "exclude": ["node_modules"]
}
子包配置(如 packages/vite/tsconfig.json ):
{
  "extends": "../../tsconfig.base.json",
  "compilerOptions": {
    "rootDir": "src",
    "outDir": "dist"
  },
  "include": ["src"]
}

类型定义与推导技巧

Vite 使用了大量的类型推导技巧以增强代码的灵活性和安全性。以下是一些关键的实践:

类型别名与接口:
type PluginOption = Plugin | false | null | undefined;
interface Plugin {
  name: string;
  apply?: () => void;
}
条件类型:
type IsDefined<T> = T extends undefined ? false : true;

type Test1 = IsDefined<string>; // true
type Test2 = IsDefined<undefined>; // false
工具类型封装:
type Mutable<T> = { -readonly [P in keyof T]: T[P] };

react-hook-form TypeScript 最佳实践

项目整体 monorepo 架构分析

react-hook-form 的代码较为集中,但在架构设计上高度模块化:

react-hook-form/
├── src/              # 核心功能代码
├── types/            # 类型定义
├── examples/         # 示例代码
├── scripts/          # 构建脚本
└── ...               # 配置文件

TypeScript 配置实践

配置亮点:
  1. 严格模式 :启用 "strict": true ,确保类型安全。
  2. 类型声明文件 :将公共类型定义提取到 types 文件夹中,便于管理。

示例:

{
  "compilerOptions": {
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true
  }
}

类型定义与推导技巧

使用泛型定义表单数据类型:
import { useForm } from 'react-hook-form';

type FormData = {
  username: string;
  password: string;
};

const { register, handleSubmit } = useForm<FormData>();
联合类型与分布式条件类型:
type FieldValue = string | number | boolean;
type IsString<T> = T extends string ? true : false;

type Test = IsString<FieldValue>; // 分别判断 string、number、boolean
递归映射类型:
type DeepPartial<T> = {
  [P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
};

Ant Design TypeScript 最佳实践

项目整体 monorepo 架构分析

Ant Design 的架构更加复杂且模块化:

ant-design/
├── components/        # 各个组件代码
├── site/              # 文档和演示
├── tests/             # 测试代码
├── scripts/           # 构建脚本
└── ...                # 配置文件

TypeScript 配置实践

配置亮点:
  1. 严格类型检查 :对组件的 props 和状态进行严格的类型定义。
  2. 模块路径映射 :通过 paths 简化模块导入。

示例:

{
  "compilerOptions": {
    "jsx": "react",
    "moduleResolution": "node",
    "baseUrl": "./",
    "paths": {
      "@components/*": ["components/*"]
    }
  }
}

类型定义与推导技巧

定义组件的 Props 类型:
import React from 'react';

interface ButtonProps {
  type?: 'primary' | 'default';
  disabled?: boolean;
}

const Button: React.FC<ButtonProps> = ({ type = 'default', disabled = false }) => {
  return <button disabled={disabled} className={`btn-${type}`}>Click me</button>;
};
高阶类型工具封装:
type Merge<T, U> = Omit<T, keyof U> & U;

interface BaseProps {
  id: string;
}

interface ExtraProps {
  id: number; // 覆盖原有类型
}

type CombinedProps = Merge<BaseProps, ExtraProps>;
复杂组件的泛型定义:
interface SelectProps<T> {
  options: T[];
  onChange: (value: T) => void;
}

function Select<T>(props: SelectProps<T>) {
  return <select>{props.options.map(option => <option>{option}</option>)}</select>;
}

TypeScript 实践总结

启用严格模式

始终启用 TypeScript 的严格模式( strict: true )。这样可以避免隐式的 any 类型,确保类型检查更加严格,并帮助发现潜在的错误。

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

使用 typeinterface 明确类型

  • 使用 interface 来定义对象的结构,尤其适用于类和对象类型。
  • 使用 type 来定义更复杂的类型(例如联合类型、交叉类型、泛型等)。
interface User {
  id: number;
  name: string;
}

type Response<T> = {
  data: T;
  success: boolean;
};

不使用 any 类型

尽量避免使用 any 类型,因为它会跳过类型检查,失去 TypeScript 的类型安全特性。代替 any ,可以使用 unknown 类型,并在需要时进行类型保护。

let value: unknown;

if (typeof value === 'string')

 {
  // 类型推断为 string
  console.log(value.length);
}

类型保护

在 TypeScript 中,类型保护是指通过某些特定的检查,确保代码在某些条件下能够推断出更加精确的类型。以下是一个类型保护的例子,用来处理 nullundefined 的情况:

function isDefined<T>(value: T | null | undefined): value is T {
  return value !== null && value !== undefined;
}

const data: string | null | undefined = 'Hello, TypeScript';

if (isDefined(data)) {
  console.log(data.toUpperCase()); // 类型推断为 string
}

通过类型保护,可以让代码更加健壮,减少不必要的类型断言。

采用模块化和类型声明文件

模块化设计

在复杂项目中,使用模块化设计将代码逻辑和类型定义进行拆分,避免一个文件过于庞大。例如:

// utils/typeGuards.ts
export function isNumber(value: unknown): value is number {
  return typeof value === 'number';
}
// utils/validators.ts
export function isValidEmail(email: string): boolean {
  const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
  return emailRegex.test(email);
}

类型声明文件

将公共类型定义放置在单独的类型声明文件中。例如:

// types/global.d.ts
declare module 'my-module' {
  export interface User {
    id: number;
    name: string;
    email: string;
  }
}

这样可以确保代码职责清晰、类型管理集中,同时减少重复代码。

静态类型检查 (基于 Zod)

Zod 是一个强大的 TypeScript 第三方库,用于定义和验证数据的静态类型,帮助提高数据的安全性和类型检查的严谨性。

基本使用

Zod 可以通过 schema 定义数据的类型,并提供强大的数据验证功能:

import { z } from 'zod';

const UserSchema = z.object({
  id: z.number(),
  name: z.string(),
  email: z.string().email(),
});

type User = z.infer<typeof UserSchema>;

const userInput = {
  id: 1,
  name: 'John Doe',
  email: 'john.doe@example.com',
};

try {
  const user: User = UserSchema.parse(userInput); // 静态类型验证
  console.log('User is valid:', user);
} catch (e) {
  console.error('Validation failed:', e.errors);
}

嵌套验证

对于复杂的数据结构,Zod 也可以通过嵌套 schema 进行验证:

const AddressSchema = z.object({
  street: z.string(),
  city: z.string(),
  zip: z.string().length(5),
});

const UserWithAddressSchema = z.object({
  id: z.number(),
  name: z.string(),
  email: z.string().email(),
  address: AddressSchema,
});

type UserWithAddress = z.infer<typeof UserWithAddressSchema>;

const userInput = {
  id: 1,
  name: 'John Doe',
  email: 'john.doe@example.com',
  address: {
    street: '123 Main St',
    city: 'Somewhere',
    zip: '12345',
  },
};

try {
  const user: UserWithAddress = UserWithAddressSchema.parse(userInput);
  console.log('User with address is valid:', user);
} catch (e) {
  console.error('Validation failed:', e.errors);
}

类型安全的动态检查

Zod 的 safeParse 方法允许您在不抛出异常的情况下安全地验证数据:

const result = UserSchema.safeParse(userInput);
if (result.success) {
  console.log('Validated User:', result.data);
} else {
  console.error('Validation Errors:', result.error.errors);
}

结合业务逻辑使用

在实际开发中,可以通过 Zod 和业务逻辑结合,将静态类型验证集成到整个项目中,例如表单校验、API 数据解析等。

// utils/validateUser.ts
import { z } from 'zod';

export const validateUser = (input: unknown): User => {
  return UserSchema.parse(input);
};

通过将 Zod 集成到项目中,可以极大地提升静态类型检查的能力,并在运行时捕获潜在的错误。

简历优化(35K+ 简历模板)

技能描述

  • 熟练掌握 HTML、CSS、JavaScript、Typescript 以及 OOP、FP、 AOP 等设计思想

  • 掌握样式体系构建与落地,对 css 预编译、css in js、module css 以及 utility-first CSS 有深入研究,并从零改良过样式体系以支持 SSR、SSG

  • 熟悉 React、Vue 相关技术栈,熟悉 React、Vue 及相关技术框架的实现原理

  • 掌握构建工具 Webpack、Vite 等,掌握编译工具 Babel,并深入理解其原理,并参与 Rspack 构建

  • 丰富的数据可视化经验,熟悉 Canvas、svg 开发范式,理解 Echarts、Antv 原理,能根据业务需求基于 d3、zrender 开发自定义渲染引擎

  • 丰富的跨端开发经验,熟练使用 Taro、Flutter、React-Native 开发跨端应用,对构建 hybird App 有丰富经验,深入理解跨端开发编译原理

  • 基于 Node.js 开发脚手架、打包构建优化工具及中间件服务

  • 掌握常用设计模式、算法与安全知识,追求开发高质量、高可维护性代码,追求极致产品体验

  • 团队管理经验,并在项目架构设计与性能优化方面具有丰富经验

  • 算法与编程技术

    • 精通各种算法题的分类及解决方法,包括排序与查找、数据结构、动态规划、贪心算法、回溯算法、分治算法、图论算法、数学算法等。
    • 重点掌握动态规划的基本概念、解题步骤和经典题目。
  • 3D 数字孪生平台开发经验

    • 熟练使用 WebGL 和 WebAssembly 技术,开发高效的 3D 渲染引擎。
    • 精通正射影像和倾斜摄影技术,具备 Tile 和模型(包括白膜和精模)的处理经验,能够使用 Blender 进行模型制作。
    • 熟悉材质、光效和粒子系统的实现与优化。
  • 全面性能优化能力

    • 具备打包构建优化经验,熟练使用 Webpack 进行模块打包,掌握 chunk、treeshaking、happypack、cache-loader 等优化技巧,并使用 Webpack Module Federation 进行模块联邦管理。
    • 精通资源优化,能够有效进行图片、字体压缩,管理请求队列,并通过 OSS 和 CDN 提升资源加载速度。
    • 具有应用性能优化经验,包括数据结构优化和应用模块更新。
    • 深入了解缓存机制,熟悉强缓存(Expiration、Cache-Control)、协商缓存(Etag)和策略缓存(Service-Worker)的配置与管理。

项目描述

这个环节至关重要,很多同学不重视,简历随便写一写就开始投递了,结果投出去几百份可能一家公司面试都没有,结果就在怀疑前端行情出问题了

STAR 法则:

  • 遇到了什么问题 question,需求
  • 怎么评估解决方案,方案对比,方案落地 react 状态管理(redux、mobx、jotai、recoil)Vue3 -> Pinia
  • 具体方案落地
  • 结果反思,细节优化思考

大家先看这段描述:

技术栈:Java、Vue2、echarts、WEui、BaiduMap、JavaScript 、HTTP数据库:MySQL管理工具:SVN

责任描述:

1)产品前端研发负责人,主要负责整体样式沟通,样式调配实现;门户、管理平台、移动端、智端、可视化等前端内容实现;

2)实现组织管理、人员管理、党员关系转接、待办通知、绩效考核(复杂功能算法实现)、发展党员(25个流程)、可视化等主体功能,兼容性优化、适配1920*1080屏幕以及响应式布局实现;

3)相关功能开发,包含前后端、数据库;

4)门户框架搭建、门户整体设计、后端接口、门户前端 UI 实现等;

5)微信小程序框架搭建、小程序页面设计及开发、知识图谱技术预演;

6 )项目经理工作辅助,包含需求沟通、UI设计沟通、交付材料项目经历整理、前端代码质量管理、部分功能设计。

深度优化一下

工作内容和成果

  • 架构设计 】参与智慧管理平台整体架构设计、技术选型与方案评审,担任全栈开发,完成相关核心模块
  • 企微开发 】对接企业微信生态,基于企微 SDK 完成平台支付、消息推送、机器人等功能开发
  • 可视化 】主导完成平台可视化渲染引擎(可视化图表的组件,数据协议)设计与开发,基于 echarts (svgRenderer、canvasRenderer 一千万行数据的表格渲染【不能使用 虚拟滚动 】 canvas table,chunk)封装业务图表库,服务于平台可视化场景
  • 地图开发 】使用百度地图 SDK,封装业务地图渲染器(MapRenderer),包含:地图撒点、地区数据下钻等功能
  • 小程序与App 】基于 uniapp 实现智慧党建用户端多端开发落地,产物编译为 H5、微信小程序两端应用
  • 团队基建 】推进团队业务组件库、图表库与基础库沉淀,完成 10+ 个业务组件沉淀,以此提升了团队协同开发效率
  • 优化 】设计产品响应式系统,基于 media query 设计响应式端点规则,适配不同端应用的展示
  • 自研 OA 打通 】...

STAR

【技术栈】

  • Java、Vue2、ECharts、WEui、BaiduMap、JavaScript、HTTP
  • 数据库 :MySQL
  • 管理工具 :SVN

【产品前端研发负责人】

  • 情境 (Situation) :担任产品前端研发负责人,负责门户、管理平台、移动端、智端、可视化等前端内容的实现。
  • 任务 (Task) :主要任务是与设计团队沟通,调配和实现整体样式,确保产品界面的一致性和用户体验。
  • 行动 (Action) :我协调设计与开发团队,定期召开样式沟通会,亲自进行样式的调配与实现,并负责不同平台和设备的前端内容开发。
  • 结果 (Result) :成功实现了多个平台的前端开发工作,提升了产品的用户体验和一致性,获得了团队和用户的高度评价。

【实现复杂功能及优化】

  • 情境 (Situation) :项目需要实现复杂功能算法和大规模功能模块,包括组织管理、人员管理、党员关系转接、待办通知、绩效考核、发展党员(25个流程)和可视化功能。
  • 任务 (Task) :负责上述复杂功能的实现,并优化其兼容性和响应式布局。
  • 行动 (Action) :通过设计和实现复杂算法,确保各模块的功能性;进行兼容性优化,使系统适配1920*1080屏幕和响应式布局。
  • 结果 (Result) :成功实现并优化了所有复杂功能,系统在不同设备和分辨率下均表现良好,提高了用户操作的流畅度和满意度。

【全面功能开发】

  • 情境 (Situation) :需要进行前后端和数据库的全面开发,确保系统各功能模块的无缝集成。
  • 任务 (Task) :开发和实现相关功能,包括前端UI、后端接口和数据库交互。
  • 行动 (Action) :采用Java、Vue2等技术,开发并调试各功能模块,与后端团队密切合作,确保接口的准确性和数据的一致性。
  • 结果 (Result) :成功完成了所有功能模块的开发和集成,系统运行稳定,性能优异,受到了客户的好评。

【微信小程序开发与知识图谱预演】

  • 情境 (Situation) :项目需要开发微信小程序,并进行知识图谱技术的预演。
  • 任务 (Task) :负责小程序框架的搭建、页面设计及开发,同时进行知识图谱的技术预演。
  • 行动 (Action) :使用WEui、JavaScript等技术,设计并开发小程序页面,进行知识图谱的技术预演和验证。
  • 结果 (Result) :成功搭建了微信小程序框架,完成了页面设计和开发工作,知识图谱技术预演顺利,通过了技术验证。

【项目经理工作辅助】

  • 情境 (Situation) :在项目中辅助项目经理,确保项目需求沟通顺畅,UI设计协调到位,交付材料齐全,前端代码质量高。
  • 任务 (Task) :辅助项目经理进行需求沟通、UI设计沟通、交付材料整理、前端代码质量管理以及部分功能设计。
  • 行动 (Action) :积极参与需求和UI设计的沟通,整理和管理项目交付材料,进行代码审查和质量管理,并参与功能设计。
  • 结果 (Result) :成功辅助项目经理完成了项目的各项工作,提高了项目的开发效率和交付质量,确保了项目的顺利进行。

其实还不够,这些项目才是求职香饽饽

你可能不具备这些项目的实战经验,很多同学写了很多年管理系统,简单增删改查项目,如果不跳出这个圈子,很难在薪资上有非常大的突破!

  • 大厂 UI 组件库(Vue3)整体设计与开发实践(monorepo 架构)

  • 大厂业务 Hooks 库(React 18)整体设计与开发实践(从零到一的架构、规范流程)

  • 企业级脚手架工具开发实践

  • 企业级文档编辑器飞书文档开发实践

  • 前端性能、异常与行为监控

  • 3D 可视化数字孪生低代码实战 💥

    • 基于 cesium(arcGis、超图) 方案的 WebGIS 开发实践
    • 基于 openlayer、mapbox 开发
    • 基于 WebGL 3D 可视化开发实践

年包 50W+ 薪资长线规划

核心要素

  1. 全面的技术储备

    1. 框架基础

      • Vue 和 React 经验:包括 Vue3 + Typescript 和 React18(Hooks、Concurrent)
      • 掌握框架原理:React 生态库(React-Router、Redux)和 Vue 生态库原理
    2. 工程化能力

      • 构建工具:Webpack、Vite、Rspack、ESBuild、swc
      • CI/CD 自动化:自动化构建和自动化部署
    3. 基建能力

      • Node.js、命令行工具开发(Cli)
      • UI 库、图表库、工具库开发
    4. 业务领域经验

      • 管理系统和图表类应用
      • 可视化、编辑器、云表格、低代码平台、SaaS 产品、数字孪生、三维可视化
  2. 项目经验

    • 参与过至少两个大型项目,并主导过一个复杂项目
    1. 管理系统:包括项目搭建、技术方案选择、技术栈构建、CI/CD 流程
    2. 其他领域项目:如可视化、编辑器、云表格、低代码平台、SaaS 产品、数字孪生、三维可视化
  3. 面试表现

    1. 个人介绍

      • 准备个人介绍草稿,涵盖基本信息、技术栈和项目重难点
    2. STAR 法则

      • 问题描述:阐述遇到的问题或需求
      • 解决方案评估:方案对比与选择(如 React 状态管理:redux、mobx、jotai、recoil,Vue3 使用 Pinia)
      • 方案实施:具体的实施步骤
      • 反思与优化:项目反思及优化建议
    3. 面试准备

      • 重点复习知识点:如 v8 内存管理、Promise A+ 规范、事件循环、this、面向对象编程原型
      • 技术储备:结合项目经验展示技术在项目中的应用
  4. 学历提升

    1. 现有学历:大专
    2. 未来计划:尽快取得本科证书(不需要注明具体年限)
    3. 学历背景:民办学校
    4. 内推建议:应对学历和工作经历问题,通过内推提升机会

补足短板

  • 项目简单,管理后台一做就是大半年,天天 CRUD

    • 看开源项目(react-hook-form ts 类型、hook 处理、状态管理、架构 Provider,keyPath)
    • 找一些不错的项目练手
    • 拿好的项目,学习完放在简历里, 可视化、编辑器、云表格、低代码、SaaS 产品、数字孪生、三维可视化
    • 1.自研:15K, 2.外包:20K ,这个火坑, 灰(供需决定)
  • 技术栈掌握不深不广,只会用 Vue2 (Vue3 + Typescript),React18(React stack reconciler)

  • 架构、方案设计没碰过

    • React,create-react-app、umi,没有真正从零到一去设计初始化过一个项目
    • Vue,Vue CLI,Vite/Webpack。Vue2 CLI 创出来项目 1. webpack、2.vite
  • 没有专精的技能或业务

    • 自驱 (假定自己是 Leader),项目的赢利点、商业价值【 可视化、编辑器、白板、团队基建、AI产品
    • 与生俱来有些东西,好奇心、自驱力、清晰规划
    • 我:管理平台,HPE(官网、后台管理),云表格(维格表、飞书云表格)、云编辑器(CKEditor 老【html string】)(语雀、【石墨文档】)

妙码学院——全程陪跑、督学、内推

⚠️ 暂不支持的文档区域,【文档小组件】

  • 跨端开发 Taro(Taro 编译器 compiler、运行时 runtime)、uniapp
  • 协同编辑器(文档类、画板类)
  • 团队基建工程(UI 库、图表库、Cli -> 产生产物 npm 包)
  • 3D 可视化数字孪生 bigdata
  • 低代码平台

课程体系 2.0 升级,除了基础知识夯实,融入了更多项目实战内容,包含:

  • 企业级脚手架工具开发实践

  • 企业级文档编辑器飞书文档开发实践

  • 大厂 UI 组件库(Vue3)整体设计与开发实践

  • 大厂业务 Hooks 库(React 18)整体设计与开发实践

  • 埋点与数据监控平台实战

  • 3D 可视化数字孪生实战 💥

    • 基于 cesium 方案的 WebGIS 开发实践
    • 基于 WebGL 3D 可视化开发实践

妙码学院全网独家项目实战矩阵

所有项目实战,均完全 从零到一手写纯原创 ,项目架构与编码规范真一线大厂级。

  • 微前端在分拆原子应用场景下的落地与实践

  • 协同编辑器从零到一架构实现

  • 推动团队基建落地

    • React UI 库
    • Vue Composition API 库
    • 企业级脚手架
  • 数字孪生平台整体架构设计

  • 企业级无代码可视化平台实践(Vue3)

  • 低代码平台设计与实现

    • 编排引擎
    • 流程引擎
    • 编辑器
    • 代码执行器与 JavaScript 沙箱
  • 用户行为分析 SDK 及监控可视化整体实现

  • 可视化渲染引擎设计与实现

  • 基于 RAG / Agent 前端 AI 应用流程编排平台

不同阶段对前端人的硬性要求

以下是对您提供的内容进行权威和专业化改写的建议:

1~3年

在此阶段,重点在于评估个人的基础知识和热情。对前端基础、计算机原理、网络通信和算法等领域的要求较高。由于在此阶段难以评估业务深度,因此更多关注基础知识的掌握程度。

  • 关键在于通过学术教育或网络资源加强基础知识;
  • 在简历中以多种方式展示对前端的热情,展现个人潜力;
  • 积极探索前沿技术,关注国内外技术动态;
  • 尝试开发小型项目或参与社区开源项目;
  • 建立技术博客,以输出促进知识吸收。

3~5年

此阶段通常是向成为独立工程师发展的关键时期,避免重复使用有限的经验。

  • 关注社区中关于进阶的资料和路线,强化基础知识;

  • 深入掌握常用框架的高级用法,探索其原理;

  • 在业务开发中不仅完成功能,还需考虑项目结构设计、封装基础工具、设计和开发基础组件;

  • 思考提高团队效率的方法,例如:

    • 集成代码检验和风格统一插件(如 eslint、stylelint、prettier、spellcheck);
    • 从工程化角度提高本地开发效率,优化webpack构建,探索esbuild、vite等工具;
    • 对于多项目开发,整理差异和统一部分,建立内部脚手架以减少重复工作;
    • 尝试搭建CI/CD平台,维护公司内部的通用npm包;
    • 培养软技能,如沟通协作,协调各角色共同推进目标。

5年以上

进入此阶段,可能朝技术专家或管理方向发展。期望您能够独立负责高复杂度项目,突破关键技术难题。

  • 负责技术调研,关注行业趋势,选择最优技术方案,具备决策能力;
  • 拥有丰富的技术经验和技术储备,能够解决遇到的困难,并有自己的方法论;
  • 协助或主导业务目标制定,合理推动项目达成预期效果;
  • 是否具有团队领导经验,能够协调跨团队项目,处理团队成员情绪问题,解决技能分布不平衡等问题;
  • 打造技术氛围,促进团队共同成长。

职业规划指导

评论区选取三位同学互动,其他同学也可以联系咨询老师,文字方式提供辅导解答。

【未知组件reminder】