一: 索引签名
索引签名用于定义对象类型,允许对象具有任意数量的属性,但属性名的类型必须是字符串(在大多数情况下)或数字(在某些特定的上下文中,如数组或类似数组的对象)。索引签名的值类型可以是任何 TypeScript 类型。
interface StringDictionary { [index: string]: string | undefined;
} let myDict: StringDictionary;
myDict["greeting"] = "hello";
console.log(myDict["greeting"]); // 输出 "hello"
二:类型索引访问
类型索引访问允许你在类型级别上访问一个对象的索引类型。在泛型编程中,这特别有用,因为你可以根据传入的类型来动态地获取该类型的索引签名类型。
1. T[number] 是一个索引访问类型(index access type),它用于从泛型类型 T 中提取数组或类数组(如元组)类型中元素的类型。
如果 T 是一个数组或元组类型,那么 T[number] 会返回该数组或元组中所有元素的共同类型(如果存在的话),或者是一个联合类型,包含了数组中所有可能的元素类型。
const tuple = ['tesla', 'model 3', 'model X', 'model Y'] as consttype TupleToObject<T extends readonly any[]> = {[P in T[number]] : P
}type result = TupleToObject<typeof tuple> // expected { 'tesla': 'tesla', 'model 3': 'model 3', 'model X': 'model X', 'model Y': 'model Y'}
2. T[0] 也是一个索引访问类型,但它特指泛型类型 T 的第一个元素的类型。
如果 T 是一个数组或元组类型,并且具有至少一个元素,那么 T[0] 将返回该数组或元组第一个元素的类型。
type NumberArray = number[];
type FirstElementTypeOfNumberArray = NumberArray[0]; // FirstElementTypeOfNumberArray 类型为 number type Tuple = [string, number, boolean];
type FirstElementTypeOfTuple = Tuple[0]; // FirstElementTypeOfTuple 类型为 string
索引访问操作符
索引访问操作符用于访问对象的属性或数组的元素,以及在类型级别上访问类型的索引签名。
--- 数组
let arr: number[] = [1, 2, 3];
type ElementType = typeof arr[number]; // ElementType 是 number let tuple: [string, number] = ['hello', 42];
type FirstElementType = typeof tuple[0]; // FirstElementType 是 string
type SecondElementType = typeof tuple[1]; // SecondElementType 是 number
--对象
interface Person { name: string; age: number; [propName: string]: any; // 索引签名 } type PropValueType = Person[string]; // PropValueType 是 any,因为索引签名的值类型是 any
--泛型
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] { return obj[key]; // 这里使用了索引访问操作符来访问 obj 的属性 } let person = { name: 'Alice', age: 30 }; let name = getProperty(person, 'name'); // name 的类型是 string,值是 'Alice'
在泛型中的应用
示例一:获取对象属性的类型const person = { name: 'Alice', age: 30, isStudent: false
};function getProperty<T, K extends keyof T>(obj: T, key: K) {return obj[key]
}const name2 = getProperty(person, 'name');示例二: 映射对象类型(每个属性的值都被转换为字符串)
type Person = { name: string; age: number; isStudent: boolean;
}; type Stringify<T> = {[P in keyof T]: string
}type PersonStringified = Stringify<Person>; // { name: string; age: string; isStudent: string; }示例三: 处理数组和元组的元素
type MapArray<T, U> = { [P in keyof T]: U;
} & { length: number }; // 这里我们简化了数组类型,仅用于演示 type NumberArray = number[];
type MappedArray = MapArray<NumberArray, string>; // 假设是 string[],但这里简化为 { [index: number]: string; length: number; } // 对于元组,我们可以更精确地处理每个元素的类型
type TupleToUnion<T extends readonly any[]> = T[number]; type Tuple = [string, number, boolean];
type TupleUnion = TupleToUnion<Tuple>; // string | number | boolean示例四:在条件类型中使用索引访问操作符 (比如我们可以创建一个类型,它根据对象是否具有某个属性来返回不同的类型。)type HasProperty <T, K> = K extends keyof T ? T[K] : neverinterface Person { name: string; age: number;
}
type NameOrNever = HasProperty<Person, 'name'>; // string
type RandomProperty = HasProperty<Person, 'random'>; // never