Portfolio
← 返回博客列表
TypeScript

2026-08-03 · 阅读 5

TypeScript

TypeScript

TypeScript 基础类型系统 - 面试复习笔记

本文档整理了 TypeScript 基础类型系统的核心知识点,适合面试准备和日常复习使用。

目录

基础类型系统

  1. 接口 vs 类型别名
  2. 联合类型与交叉类型
  3. 泛型
  4. 类型守卫
  5. 类型推断
  6. 函数类型
  7. 类类型

高级特性

  1. 装饰器
  2. 工具类型
  3. 条件类型与映射类型
  4. 工程化与配置

1. 接口 vs 类型别名

核心概念

接口(Interface):

  • 用于定义对象的形状(结构)
  • 可以被类实现(implements)
  • 可以继承(extends)
  • 支持声明合并

类型别名(Type Alias):

  • 可以给任何类型起别名(不仅限于对象)
  • 更灵活,支持联合类型、交叉类型、元组等
  • 不能被类实现
  • 不支持声明合并

代码示例

// 1. 基本对象定义 - 两者都可以
interface IUser {
  name: string;
  age: number;
}

type TUser = {
  name: string;
  age: number;
};

// 2. 类型别名可以定义任何类型
type ID = string | number;  // 联合类型
type Tuple = [string, number];  // 元组
type Callback = (data: string) => void;  // 函数类型

// 3. 接口可以继承
interface IAdmin extends IUser {
  permissions: string[];
}

// 类型别名使用交叉类型实现继承
type TAdmin = TUser & {
  permissions: string[];
};

// 4. 接口支持声明合并
interface Config {
  host: string;
}

interface Config {
  port: number;
}
// 最终 Config = { host: string; port: number; }

// 5. 类只能实现接口
class UserImpl implements IUser {
  name = "John";
  age = 30;
}

面试考点

问: 什么时候用接口,什么时候用类型别名?

:

  • 用接口: 定义对象的形状、需要被类实现、需要继承扩展
  • 用类型别名: 联合类型、交叉类型、元组、函数类型、基本类型别名

2. 联合类型与交叉类型

核心概念

联合类型(Union Types):

  • 表示"或"的关系,使用 | 操作符
  • 一个值可以是多种类型之一
  • 常用于函数参数、返回值、变量定义

交叉类型(Intersection Types):

  • 表示"且"的关系,使用 & 操作符
  • 一个值必须同时满足所有类型
  • 常用于对象合并、Mixin 模式

代码示例

// 1. 联合类型 - "或"的关系
type ID = string | number;
type Status = 'pending' | 'success' | 'failed';

function printId(id: ID) {
  console.log(id);
}

printId('abc');  // ✅
printId(123);    // ✅

// 2. 交叉类型 - "且"的关系
interface Business {
  name: string;
  businessType: string;
}

interface Contact {
  email: string;
  phone: string;
}

type BusinessCard = Business & Contact;

const card: BusinessCard = {
  name: '公司A',
  businessType: '科技',
  email: 'a@company.com',
  phone: '123-456-7890'
};

// 3. 交叉类型的冲突情况
interface A {
  name: string;
  age: number;
}

interface B {
  name: number;  // 与 A 的 name 类型冲突
  gender: string;
}

type Conflict = A & B;
// Conflict 的 name 属性类型是 string & number = never

面试考点

问: 联合类型如何进行类型收窄?

: 使用类型守卫缩小类型范围。

// 方法1: typeof 类型守卫
function func1(value: string | number) {
  if (typeof value === 'string') {
    // value: string
  } else {
    // value: number
  }
}

// 方法2: instanceof
function func2(value: Date | string) {
  if (value instanceof Date) {
    // value: Date
  } else {
    // value: string
  }
}

// 方法3: in 操作符
interface A { a: string; }
interface B { b: number; }

function func3(value: A | B) {
  if ('a' in value) {
    // value: A
  } else {
    // value: B
  }
}

// 方法4: 字面量类型判断
type Status = 'pending' | 'success';

function func4(status: Status) {
  if (status === 'pending') {
    // status: 'pending'
  } else {
    // status: 'success'
  }
}

3. 泛型

核心概念

泛型(Generics):

  • 参数化类型,在定义时不指定具体类型,使用时再确定
  • 提供代码复用性和类型安全性
  • 使用 <T> 语法定义泛型参数

代码示例

// 1. 泛型函数
function identity<T>(arg: T): T {
  return arg;
}

let output1 = identity<string>('hello');  // 明确指定 T 为 string
let output2 = identity(123);               // 类型推断,T 为 number

// 2. 泛型接口
interface Container<T> {
  value: T;
  getValue(): T;
}

const stringContainer: Container<string> = {
  value: 'hello',
  getValue() { return this.value; }
};

// 3. 泛型类
class GenericBox<T> {
  constructor(private content: T) {}

  getContent(): T {
    return this.content;
  }
}

const numberBox = new GenericBox<number>(42);

// 4. 实际应用: 合并对象
function merge<T, U>(obj1: T, obj2: U): T & U {
  return { ...obj1, ...obj2 };
}

const result = merge({ name: 'John' }, { age: 30 });
// result: { name: string } & { age: number }

// 5. 泛型约束
interface Lengthwise {
  length: number;
}

function logLength<T extends Lengthwise>(arg: T): T {
  console.log(arg.length);  // 可以访问 length 属性
  return arg;
}

logLength('hello');  // ✅ 字符串有 length 属性
logLength([1, 2, 3]);  // ✅ 数组有 length 属性
// logLength(123);  // ❌ 数字没有 length 属性

面试考点

问: 泛型的作用是什么?

:

  1. 让函数/类可以处理任意类型的数据
  2. 保持类型安全,返回值类型与参数类型一致
  3. 提高代码复用性,避免重复代码

4. 类型守卫

核心概念

类型守卫(Type Guards):

  • 在运行时检查变量的类型
  • 在代码块内缩小变量的类型范围
  • 常用方式: typeofinstanceofin 操作符、字面量判断

代码示例

// 1. typeof 类型守卫
function processValue(value: string | number) {
  if (typeof value === 'string') {
    console.log(value.toUpperCase());  // value: string
  } else {
    console.log(value.toFixed(2));     // value: number
  }
}

// 2. instanceof 类型守卫(仅适用于类)
class Dog {
  bark() { console.log('汪汪'); }
}

class Cat {
  meow() { console.log('喵喵'); }
}

function makeSound(animal: Dog | Cat) {
  if (animal instanceof Dog) {
    animal.bark();  // animal: Dog
  } else {
    animal.meow();  // animal: Cat
  }
}

// 3. in 操作符类型守卫
interface Admin {
  name: string;
  permissions: string[];
}

interface User {
  name: string;
  email: string;
}

function getInfo(user: Admin | User) {
  if ('permissions' in user) {
    console.log(user.permissions);  // user: Admin
  } else {
    console.log(user.email);        // user: User
  }
}

// 4. 字面量类型守卫(适用于接口)
interface Bird {
  type: 'bird';
  fly(): void;
}

interface Fish {
  type: 'fish';
  swim(): void;
}

function move(animal: Bird | Fish) {
  if (animal.type === 'bird') {
    animal.fly();   // animal: Bird
  } else {
    animal.swim();  // animal: Fish
  }
}

面试考点

问: 接口为什么不能用 instanceof?

:

  • 接口只存在于 TypeScript 编译阶段,编译成 JavaScript 后会被完全移除
  • 运行时不存在接口,无法使用 instanceof 检查
  • 应该使用字面量判断或 in 操作符

5. 类型推断

核心概念

类型推断(Type Inference):

  • TypeScript 自动推断变量的类型,无需显式声明
  • 根据初始值、上下文、返回值等推断类型
  • 提高代码简洁性,但有时需要显式声明增加可读性

代码示例

// 1. 变量初始化推断
let name = 'Alice';      // TypeScript 推断为 string
let age = 30;            // TypeScript 推断为 number
let isStudent = true;    // TypeScript 推断为 boolean

// name = 123;           // ❌ 不能将 number 赋值给 string

// 2. 函数返回值推断
function add(a: number, b: number) {
  return a + b;          // TypeScript 推断返回值是 number
}

const result = add(1, 2);  // result: number

// 3. 数组元素类型推断
const numbers = [1, 2, 3];      // number[]
const mixed = [1, 'a', true];   // (number | string | boolean)[]

// 4. 上下文类型推断
const numbers2 = [1, 2, 3];
numbers2.forEach(num => {
  console.log(num.toFixed(2));  // TypeScript 知道 num 是 number
});

// 5. 未初始化的变量
let x;  // x: any (未初始化,TypeScript 推断为 any)

// 6. 联合类型的推断
const value = Math.random() > 0.5 ? 'hello' : 123;
// value: string | number (TypeScript 正确推断为联合类型)

面试考点

问: 什么时候需要显式声明类型?

:

  1. 复杂类型,提高可读性
  2. 联合类型,TypeScript 无法推断
  3. 函数参数,TypeScript 无法推断
  4. 对象属性,明确接口约束
// 1. 复杂类型
interface User {
  id: number;
  name: string;
  email: string;
}
const user: User = { id: 1, name: 'Alice', email: 'alice@example.com' };

// 2. 联合类型
let result: string | number;

// 3. 函数参数
function greet(name: string) {
  console.log(`Hello, ${name}`);
}

6. 函数类型

核心概念

函数类型:

  • 定义函数的参数类型和返回值类型
  • 提供类型安全的函数调用
  • 支持函数重载、可选参数、默认参数等特性

代码示例

// 1. 函数声明
function add(a: number, b: number): number {
  return a + b;
}

// 2. 函数表达式
const subtract = (a: number, b: number): number => {
  return a - b;
};

// 3. 类型别名定义函数类型
type MathOperation = (a: number, b: number) => number;

const multiply: MathOperation = (a, b) => a * b;

// 4. 接口定义函数类型
interface Calculator {
  (a: number, b: number): number;
}

const divide: Calculator = (a, b) => a / b;

// 5. 可选参数
function greet(name: string, greeting?: string): string {
  return `${greeting || 'Hello'}, ${name}!`;
}

greet('Alice');              // "Hello, Alice!"
greet('Alice', 'Hi');        // "Hi, Alice!"

// 6. 默认参数
function greet2(name: string, greeting: string = 'Hello'): string {
  return `${greeting}, ${name}!`;
}

greet2('Bob');               // "Hello, Bob!"

// 7. 剩余参数
function sum(...numbers: number[]): number {
  return numbers.reduce((total, num) => total + num, 0);
}

sum(1, 2, 3, 4);  // 10

// 8. 函数重载
function formatValue(value: string): string;
function formatValue(value: number): string;
function formatValue(value: string | number): string {
  if (typeof value === 'string') {
    return value.toUpperCase();
  } else {
    return value.toFixed(2);
  }
}

面试考点

问: 可选参数的位置规则?

:

  • 可选参数必须在必选参数后面
  • 可选参数不能在必选参数前面
// ✅ 正确: 可选参数在后面
function greet(name: string, greeting?: string): string {
  return `${greeting || 'Hello'}, ${name}!`;
}

// ❌ 错误: 可选参数在前面
// function greet2(greeting?: string, name: string): string { }  // 编译错误!

7. 类类型

核心概念

类类型:

  • TypeScript 为 ES6 类添加了类型系统
  • 包括属性类型、方法类型、访问修饰符等
  • 支持接口实现、泛型类、抽象类等特性

代码示例

// 1. 基本类类型定义
class User {
  name: string;
  age: number;
  private id: number;       // 私有属性
  protected email: string;   // 受保护属性
  readonly createdAt: Date;  // 只读属性

  constructor(name: string, age: number, id: number) {
    this.name = name;
    this.age = age;
    this.id = id;
    this.createdAt = new Date();
  }

  greet(): string {
    return `Hello, I'm ${this.name}`;
  }
}

// 2. 访问修饰符
class Example {
  public a: string;      // 任何地方都可以访问
  private b: number;     // 只能在 Example 类内部访问
  protected c: boolean;  // 只能在 Example 类及其子类中访问
}

class ChildExample extends Example {
  constructor() {
    super();
    this.a = 'hello';     // ✅ public 可以访问
    // this.b = 123;      // ❌ private 不能在子类访问
    this.c = true;        // ✅ protected 可以在子类访问
  }
}

// 3. 类实现接口
interface IEntity {
  id: number;
  save(): void;
}

class Product implements IEntity {
  id: number;

  constructor(id: number) {
    this.id = id;
  }

  save(): void {
    console.log('Saving product...');
  }
}

// 4. 泛型类
class Container<T> {
  private value: T;

  constructor(value: T) {
    this.value = value;
  }

  getValue(): T {
    return this.value;
  }

  setValue(value: T): void {
    this.value = value;
  }
}

const numberContainer = new Container<number>(42);
const stringContainer = new Container<string>('hello');

// 5. 抽象类
abstract class Animal {
  abstract makeSound(): void;  // 抽象方法,子类必须实现

  move(): void {  // 普通方法,子类可以直接使用
    console.log('Moving...');
  }
}

class Dog extends Animal {
  makeSound(): void {
    console.log('汪汪');
  }
}

// 6. 实战案例: 队列类
class Queue<T> {
    private items: T[] = [];

    enqueue(item: T): void {
        this.items.push(item);
    }

    dequeue(): T | undefined {
        return this.items.shift();
    }

    peek(): T | undefined {
        return this.items[0];
    }

    size(): number {
        return this.items.length;
    }
}

const numberQueue = new Queue<number>();
numberQueue.enqueue(1);
numberQueue.enqueue(2);
console.log(numberQueue.dequeue());  // 1

面试考点

问: 三种访问修饰符的区别?

:

  • public: 任何地方都可以访问(默认)
  • private: 只能在类内部访问
  • protected: 只能在类内部和子类中访问

8. 装饰器

核心概念

装饰器(Decorators):

  • 一种特殊类型的声明,可以附加到类、方法、属性、参数上
  • 用于修改或增强类和类的成员
  • 本质是一个函数,在运行时被调用
  • 常用于: 日志记录、性能监控、权限控制等

装饰器类型

// 1. 类装饰器
function sealed(constructor: Function) {
  Object.seal(constructor);
  Object.seal(constructor.prototype);
}

@sealed
class BankAccount {
  constructor(public balance: number) {}
}

// 2. 方法装饰器
function log(
  target: any,
  propertyKey: string,
  descriptor: PropertyDescriptor
) {
  const originalMethod = descriptor.value;

  descriptor.value = function(...args: any[]) {
    console.log(`调用方法: ${propertyKey}`);
    const result = originalMethod.apply(this, args);
    return result;
  };

  return descriptor;
}

class Calculator {
  @log
  add(a: number, b: number) {
    return a + b;
  }
}

// 3. 属性装饰器
function readonly(target: any, propertyKey: string) {
  Object.defineProperty(target, propertyKey, {
    writable: false
  });
}

class Person {
  @readonly
  name: string = 'Alice';
}

// 4. 参数装饰器
function required(
  target: any,
  propertyKey: string,
  parameterIndex: number
) {
  console.log(`参数 ${parameterIndex} 是必需的`);
}

class UserService {
  getUser(@required id: number, name: string) {
    // ...
  }
}

// 5. 装饰器工厂
function configurable(value: boolean) {
  return function(
    target: any,
    propertyKey: string,
    descriptor: PropertyDescriptor
  ) {
    descriptor.configurable = value;
    return descriptor;
  };
}

class Point {
  @configurable(false)
  get x() { return this._x; }
}

实际应用场景

// 1. 日志记录
function logExecution(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
  const original = descriptor.value;

  descriptor.value = function(...args: any[]) {
    const start = Date.now();
    const result = original.apply(this, args);
    const duration = Date.now() - start;
    console.log(`${propertyKey} 执行时间: ${duration}ms`);
    return result;
  };
}

class DataProcessor {
  @logExecution
  processData(data: any) {
    return data;
  }
}

// 2. 权限控制
function requireAuth(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
  const original = descriptor.value;

  descriptor.value = function(...args: any[]) {
    if (!this.isAuthenticated) {
      throw new Error('未授权访问');
    }
    return original.apply(this, args);
  };
}

class AdminPanel {
  isAuthenticated = false;

  @requireAuth
  deleteUser(userId: number) {
    console.log(`删除用户 ${userId}`);
  }
}

// 3. 缓存
function cache(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
  const original = descriptor.value;
  const cacheMap = new Map();

  descriptor.value = function(...args: any[]) {
    const key = JSON.stringify(args);
    if (cacheMap.has(key)) {
      return cacheMap.get(key);
    }
    const result = original.apply(this, args);
    cacheMap.set(key, result);
    return result;
  };
}

class ApiService {
  @cache
  fetchData(id: number) {
    console.log('发起网络请求');
    return { id, data: 'some data' };
  }
}

面试考点

问: 装饰器的执行顺序是什么?

: 装饰器工厂从上到下执行,装饰器本身从下到上执行(洋葱模型)

@first()   // ① first工厂执行
@second()  // ② second工厂执行
method() {}

// 装饰器执行顺序:
// ③ second装饰器执行
// ④ first装饰器执行

记忆口诀: 工厂从上到下,装饰器从下到上


9. 工具类型

核心概念

工具类型(Utility Types):

  • TypeScript 内置的类型转换工具
  • 用于快速创建新类型,避免重复定义
  • 都是泛型类型,可以灵活组合使用

常用工具类型

// 1. Partial<T> - 将所有属性变为可选
interface User {
  id: number;
  name: string;
  email: string;
}

type PartialUser = Partial<User>;
// { id?: number; name?: string; email?: string; }

// 实际应用: 更新用户信息
function updateUser(id: number, updates: Partial<User>) {
  // 只需要传入要更新的字段
}

updateUser(1, { name: 'Alice' });  // ✅ 只更新名字

// 2. Required<T> - 将所有属性变为必需
type RequiredUser = Required<PartialUser>;
// { id: number; name: string; email: string; }

// 3. Readonly<T> - 将所有属性变为只读
type ReadonlyUser = Readonly<User>;
// { readonly id: number; readonly name: string; readonly email: string; }

// 4. Pick<T, K> - 从类型 T 中选取部分属性
type UserPreview = Pick<User, 'id' | 'name'>;
// { id: number; name: string; }

// 5. Omit<T, K> - 从类型 T 中排除部分属性
type UserBasic = Omit<User, 'email'>;
// { id: number; name: string; }

// 6. Record<K, T> - 创建对象类型
type UserRoles = Record<string, 'admin' | 'user' | 'guest'>;
// { [key: string]: 'admin' | 'user' | 'guest'; }

// 7. Extract<T, U> - 提取符合类型的类型
type T0 = Extract<'a' | 'b' | 'c', 'a' | 'f'>;  // 'a'

// 8. Exclude<T, U> - 排除符合类型的类型
type T1 = Exclude<'a' | 'b' | 'c', 'a'>;  // 'b' | 'c'

// 9. NonNullable<T> - 排除 null 和 undefined
type T2 = NonNullable<string | null | undefined>;  // string

// 10. ReturnType<T> - 获取函数返回值类型
function getUser() {
  return { id: 1, name: 'Alice' };
}

type User2 = ReturnType<typeof getUser>;
// { id: number; name: string; }

// 11. Parameters<T> - 获取函数参数类型
function createUser(name: string, age: number) {
  return { name, age };
}

type CreateUserParams = Parameters<typeof createUser>;
// [string, number]

实战应用案例

interface Article {
  id: number;
  title: string;
  content: string;
  author: string;
  createdAt: Date;
  updatedAt: Date;
}

// 创建文章:用户只需要填写基础信息
type CreateArticle = Omit<Article, 'id' | 'createdAt' | 'updatedAt'>;

// 更新文章:用户可以修改内容,但不能修改 id 和时间
type UpdateArticle = Partial<Omit<Article, 'id' | 'createdAt' | 'updatedAt'>>;

// 列表展示:精简信息
type ArticleListItem = Pick<Article, 'id' | 'title' | 'author' | 'createdAt'>;

// 使用示例
function createArticle(data: CreateArticle): Article {
  return {
    id: Math.random(),
    ...data,
    createdAt: new Date(),
    updatedAt: new Date()
  };
}

function updateArticle(id: number, updates: UpdateArticle): void {
  // updates: { title?: string; content?: string; author?: string; }
}

面试考点

问: Partial 和 Omit<T, K> 的区别?

:

  • Partial<T>: 将所有属性变为可选
  • Omit<T, K>: 排除指定属性
interface User {
  id: number;
  name: string;
}

type PartialUser = Partial<User>;  // { id?: number; name?: string; }
type OmitUser = Omit<User, 'id'>;  // { name: string; }

10. 条件类型与映射类型

条件类型

条件类型(Conditional Types):

  • 根据类型关系决定最终类型
  • 使用 extends 关键字进行条件判断
  • 类似于三元运算符 T extends U ? X : Y
// 1. 基础条件类型
type IsString<T> = T extends string ? 'string' : 'not string';

type A = IsString<string>;  // 'string'
type B = IsString<number>;  // 'not string'

// 2. 提取函数返回值类型
type GetReturnType<T> = T extends (...args: any[]) => infer R ? R : never;

function getString() { return 'hello'; }
type StringReturn = GetReturnType<typeof getString>;  // string

// 3. 提取数组元素类型
type ElementType<T> = T extends (infer E)[] ? E : never;

type StringArray = ElementType<string[]>;  // string

映射类型

映射类型(Mapped Types):

  • 基于旧类型创建新类型
  • 使用 in 关键字遍历属性
  • 可以批量转换属性类型
// 1. 基础映射类型
type Readonly<T> = {
  readonly [P in keyof T]: T[P];
};

interface User {
  name: string;
  age: number;
}

type ReadonlyUser = Readonly<User>;
// { readonly name: string; readonly age: number; }

// 2. 可选属性映射
type Optional<T> = {
  [P in keyof T]?: T[P];
};

type OptionalUser = Optional<User>;
// { name?: string; age?: number; }

// 3. 过滤属性类型
type ExtractByType<T, U> = {
  [P in keyof T as T[P] extends U ? P : never]: T[P];
};

interface Product {
  id: number;
  name: string;
  price: number;
  description: string;
}

type StringProperties = ExtractByType<Product, string>;
// { name: string; description: string; }

// 4. 添加前缀
type AddPrefix<T, P extends string> = {
  [K in keyof T as `${P}${string & K}`]: T[K];
};

type PrefixedUser = AddPrefix<User, 'user_'>;
// { user_name: string; user_age: number; }

面试考点

问: 条件类型中 infer 关键字的作用?

: infer 用于在条件类型中推断类型,可以在 extends 子句中定义类型变量

type GetReturnType<T> = T extends (...args: any[]) => infer R ? R : never;
// infer R 表示推断返回值类型并赋值给 R

11. 工程化与配置

tsconfig.json 核心配置

{
  "compilerOptions": {
    // 基本选项
    "target": "ES2020",              // 编译目标版本
    "module": "ESNext",              // 模块系统
    "lib": ["ES2020", "DOM"],        // 编译时包含的库

    // 严格模式
    "strict": true,                  // 启用所有严格类型检查
    "noImplicitAny": true,          // 不允许隐式 any
    "strictNullChecks": true,       // 严格的 null 检查

    // 模块解析
    "moduleResolution": "node",     // 模块解析策略
    "baseUrl": "./",                // 基础路径
    "paths": {
      "@/*": ["src/*"]              // 路径别名
    },

    // 输出配置
    "outDir": "./dist",             // 输出目录
    "rootDir": "./src",             // 源代码目录
    "declaration": true,            // 生成 .d.ts 声明文件
    "sourceMap": true,              // 生成 sourceMap

    // 其他选项
    "esModuleInterop": true,        // 允许 CommonJS 模块导入
    "skipLibCheck": true,           // 跳过库文件类型检查
    "forceConsistentCasingInFileNames": true
  },

  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist"]
}

声明文件

// 1. 全局声明文件 (global.d.ts)
declare const API_URL: string;
declare function log(message: string): void;

// 2. 模块声明文件
declare module 'my-library' {
  export function greet(name: string): string;
  export class Calculator {
    add(a: number, b: number): number;
  }
}

// 3. 为第三方库补充类型
declare module 'lodash' {
  export function debounce<T extends (...args: any[]) => any>(
    func: T,
    wait?: number
  ): T;
}

// 4. 声明合并
interface Window {
  myCustomProperty: string;
}

面试考点

问: strict: true 包含哪些严格模式选项?

: strict: true 等同于同时启用以下所有选项:

{
  "noImplicitAny": true,                    // 不允许隐式 any
  "strictNullChecks": true,                 // 严格的 null 检查
  "strictFunctionTypes": true,              // 严格的函数类型检查
  "strictBindCallApply": true,              // 严格的 bind/call/apply 检查
  "strictPropertyInitialization": true,    // 严格的属性初始化检查
  "noImplicitThis": true,                   // 不允许隐式 this
  "alwaysStrict": true,                     // 总是使用严格模式
  "useUnknownInCatchVariables": true        // catch 子句变量为 unknown
}

问: 第三方库没有类型定义怎么办?

:

  1. 安装官方类型定义包: npm install --save-dev @types/library-name
  2. 创建自定义声明文件: src/types/library-name.d.ts
  3. 临时使用 any 断言(不推荐)

总结

基础类型系统 - 面试高频考点

  1. 接口 vs 类型别名: 接口用于对象形状定义,类型别名更灵活
  2. 联合类型 vs 交叉类型: 联合类型是"或"的关系,交叉类型是"且"的关系
  3. 泛型的作用: 提高代码复用性,保持类型安全
  4. 类型守卫: 在运行时检查类型,缩小类型范围
  5. 类型推断: TypeScript 自动推断类型,但复杂情况需要显式声明
  6. 函数类型: 注意可选参数位置规则
  7. 类类型: 掌握访问修饰符和泛型类的使用

高级特性 - 面试高频考点

  1. 装饰器: 掌握装饰器类型和执行顺序(工厂从上到下,装饰器从下到上)
  2. 工具类型: 常用 Partial、Omit、Pick、Record 等工具类型的使用场景
  3. 条件类型与映射类型: infer 关键字和映射类型的基本用法
  4. 工程化配置: strict 模式和第三方库类型定义的处理方法

学习建议

  1. 理解概念: 先理解每个知识点的核心概念
  2. 多写代码: 通过实际代码加深理解
  3. 面试题练习: 通过面试题检验掌握程度
  4. 实际应用: 在项目中使用 TypeScript 加深印象