ts: 索引类型

一: 索引签名

索引签名用于定义对象类型,允许对象具有任意数量的属性,但属性名的类型必须是字符串(在大多数情况下)或数字(在某些特定的上下文中,如数组或类似数组的对象)。索引签名的值类型可以是任何 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 const

type 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
  1. T[]标识泛型数组
type NodeA = {
    type: "A"
    name: string
    flag: number
  }
  type NodeB = {
    type: "B"
    id: number
    flag: number
  }
  type NodeC = {
    type: "C"
    name: string
    flag: number
  }
  
  type Nodes = NodeA | NodeB | NodeC
type ReplacedNodes = ReplaceKeys<Nodes>
// type ReplaceKeys<T> 
// =  T[] extends [NodeA , NodeB , NodeC] ? true : false // false
type ReplaceKeys<T> 
=  T[] extends (NodeA|NodeB|NodeC)[] ? true : false // true

索引访问操作符

索引访问操作符用于访问对象的属性或数组的元素,以及在类型级别上访问类型的索引签名。

--- 数组
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] : never

interface Person {  
  name: string;  
  age: number;
}
type NameOrNever = HasProperty<Person, 'name'>; // string  
type RandomProperty = HasProperty<Person, 'random'>; // never

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值