【TypeScript】索引签名类型(Index Signatures)

索引签名类型

索引签名(Index Signatures)允许定义对象中动态属性名的类型规则,特别适合处理键值对集合或不确定属性名的对象结构。

🏷️ 基本语法

interface Dictionary {
  [key: string]: number; // 字符串索引签名
}

interface NumericDictionary {
  [index: number]: string; // 数字索引签名
}

🌟 核心特性

1. 字符串索引签名

interface StringKeyObject {
  [key: string]: any; // 允许任意字符串作为键
  name: string;       // ✅ 可以包含已知属性(必须符合索引签名约束)
}

const obj: StringKeyObject = {
  name: "Alice",
  age: 30,            // ✅ 符合 [key: string]: any
  "favorite-color": "blue"
};

2. 数字索引签名

interface NumberKeyArray {
  [index: number]: string; // 类似数组的结构
  length: number;          // 可以包含其他属性
}

const arr: NumberKeyArray = {
  0: "first",
  1: "second",
  length: 2
};

3. 混合索引签名

interface HybridDictionary {
  [key: string]: string | number;
  [index: number]: string;  // 数字索引返回值必须是字符串索引的子类型
  id: number;              // 已知属性必须符合索引签名
}

🛠️ 实际应用场景

1. 动态属性对象

interface DynamicConfig {
  [setting: string]: boolean | string;
  debugMode: boolean; // 特定已知属性
}

const config: DynamicConfig = {
  debugMode: true,
  "feature.autoSave": true,
  "ui.theme": "dark"
};

2. 类型安全的字典

interface WordDictionary {
  [word: string]: {
    definition: string;
    synonyms: string[];
  };
}

const dictionary: WordDictionary = {
  "ephemeral": {
    definition: "lasting for a very short time",
    synonyms: ["transient", "fleeting"]
  }
};

3. 模拟数组结构

interface MyArray<T> {
  [n: number]: T;
  length: number;
  push(...items: T[]): number;
}

const nums: MyArray<number> = {
  0: 1,
  1: 2,
  length: 2,
  push: function(...items) { /* 实现 */ }
};

⚠️ 重要限制与注意事项

  1. 类型一致性规则

    interface Problematic {
      [key: string]: number;
      name: string; // ❌ 错误:string 不符合 number
    }
    
  2. 只读索引签名

    interface ReadonlyMap {
      readonly [key: string]: number;
    }
    
    const map: ReadonlyMap = { count: 1 };
    // map.count = 2; ❌ 错误:只读属性
    
  3. 与 Record 工具类型的区别

    // 索引签名方式
    interface StringToNumber {
      [key: string]: number;
    }
    
    // Record 方式
    type StringToNumber = Record<string, number>;
    
    /* 区别:
       - Record 更简洁
       - 索引签名可以在接口中与其他属性共存
    */
    

🚀 高级技巧

1. 模板字面量索引签名(TS 4.4+)

interface Headers {
  [header: `x-${string}`]: string;
  "content-type": string;
}

const headers: Headers = {
  "x-request-id": "123",
  "x-api-key": "secret",
  "content-type": "application/json"
  // "auth-token": "xxx" ❌ 不符合模板
};

2. 条件索引签名

type Conditional<T> = T extends "readonly" 
  ? { readonly [key: string]: number } 
  : { [key: string]: number };

const readOnlyDict: Conditional<"readonly"> = { count: 1 };
// readOnlyDict.count = 2; ❌ 错误

索引签名是 TypeScript 灵活类型系统的关键特性之一,合理使用可以:

  • 处理动态数据结构 🔄
  • 保持类型安全 🛡️
  • 减少 any 的使用 🚫
  • 提高代码可维护性 🧹
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值