可索引类型用于描述可以通过索引访问的类型,如数组和对象。
interface StringArray {
[index: number]: string
}
const names: StringArray = ["张三", "李四", "王五"]
console.log(names[0]) // "张三"
interface StringDictionary {
[key: string]: string
}
const dict: StringDictionary = {
name: "张三",
city: "北京",
country: "中国"
}
console.log(dict["name"]) // "张三"
同时具有固定属性和索引签名:
interface UserCollection {
[key: string]: User | number
count: number
}
interface User {
id: number
name: string
}
const users: UserCollection = {
count: 2,
"user1": { id: 1, name: "张三" },
"user2": { id: 2, name: "李四" }
}
索引签名的返回值类型必须兼容所有属性:
interface Dictionary {
[key: string]: string | number
name: string // 正确:string 兼容
age: number // 正确:number 兼容
active: boolean // 错误:boolean 不兼容
}
interface ReadonlyStringArray {
readonly [index: number]: string
}
const names: ReadonlyStringArray = ["张三", "李四"]
names[0] = "王五" // 错误:只读
interface Config {
[key: string]: string | number | boolean
}
const config: Config = {
apiUrl: "https://api.example.com",
timeout: 5000,
debug: true
}
function getConfig(key: string): string | number | boolean | undefined {
return config[key]
}
interface Cache<T> {
[key: string]: T
}
class MemoryCache<T> {
private cache: Cache<T> = {}
set(key: string, value: T): void {
this.cache[key] = value
}
get(key: string): T | undefined {
return this.cache[key]
}
has(key: string): boolean {
return key in this.cache
}
delete(key: string): void {
delete this.cache[key]
}
}
const userCache = new MemoryCache<User>()
userCache.set("user:1", { id: 1, name: "张三" })
console.log(userCache.get("user:1"))
interface EventMap {
[eventName: string]: (...args: any[]) => void
}
class EventEmitter {
private events: EventMap = {}
on(event: string, handler: (...args: any[]) => void): void {
this.events[event] = handler
}
emit(event: string, ...args: any[]): void {
const handler = this.events[event]
if (handler) {
handler(...args)
}
}
}
interface TranslationDictionary {
[key: string]: string
}
const translations: TranslationDictionary = {
"hello": "你好",
"world": "世界",
"goodbye": "再见"
}
function translate(key: string): string {
return translations[key] ?? key
}
console.log(translate("hello")) // "你好"
console.log(translate("unknown")) // "unknown"
interface Style {
[property: string]: string
}
const style: Style = {
color: "red",
fontSize: "16px",
marginTop: "10px"
}
function applyStyle(element: HTMLElement, style: Style): void {
Object.assign(element.style, style)
}
使用 Record 创建索引类型:
type UserMap = Record<string, User>
const users: UserMap = {
"user1": { id: 1, name: "张三" },
"user2": { id: 2, name: "李四" }
}
使用索引访问获取类型:
interface User {
id: number
name: string
email: string
}
type UserId = User["id"] // number
type UserName = User["name"] // string
type UserKeys = keyof User // "id" | "name" | "email"
JavaScript 会将数字索引转换为字符串:
interface ArrayLike {
[index: number]: string
length: number
}
const arr: ArrayLike = {
0: "a",
1: "b",
length: 2
}
console.log(arr[0]) // "a"
console.log(arr["0"]) // "a"(相同)
索引签名会放宽类型检查:
interface Loose {
[key: string]: any
}
const obj: Loose = {
name: "张三",
age: 25,
doSomething: () => {}
}
obj.anything // any 类型
interface Strict {
[key: string]: string | number | undefined
name: string
age: number
}
const obj: Strict = {
name: "张三",
age: 25
}
obj.unknown // string | number | undefined