返回
谈谈 TypeScript 的奇妙用法
前端
2023-09-26 01:43:08
在 TypeScript 中,keyof
操作符可以获取类型的所有属性名,然后使用 in
进行遍历,将值赋给 P
,最后使用 T[P]
取得相应属性的值。但是,这只能适用于一层嵌套的情况,如上面的 Partial
例子来看,jack.person.name
是可以直接修改的。
上面的 - ?
很好理解,就是将可选项代表的 ?
去掉,从而将属性声明为必选。Pick<T, K>
是从 T
中挑选出 K
所指定的属性,组成一个新的类型。Omit<T, K>
是从 T
中排除 K
所指定的属性,组成一个新的类型。
让我们深入探索这些类型操作的奇妙用法:
-
获取对象的所有属性名:
interface Person { name: string; age: number; city: string; } type PersonKeys = keyof Person; // "name" | "age" | "city"
现在,我们可以使用
PersonKeys
来遍历Person
对象的所有属性:function logPersonKeys(person: Person) { for (const key of Object.keys(person) as PersonKeys) { console.log(key, person[key]); } } logPersonKeys({ name: "Alice", age: 25, city: "London" }); // "name" "Alice" // "age" 25 // "city" "London"
-
根据条件筛选属性:
我们可以使用条件类型来根据条件筛选属性:
type NameOrAge<T> = T extends { name: string; age: number } ? "name" | "age" : never; interface Person { name: string; age: number; city: string; } type PersonNameOrAge = NameOrAge<Person>; // "name" | "age"
现在,我们可以使用
PersonNameOrAge
来挑选出Person
对象中name
和age
这两个属性:function logPersonNameOrAge(person: Person) { for (const key of Object.keys(person) as PersonNameOrAge) { console.log(key, person[key]); } } logPersonNameOrAge({ name: "Alice", age: 25, city: "London" }); // "name" "Alice" // "age" 25
-
创建映射类型:
我们可以使用映射类型来创建新的类型,其中每个属性的值都是根据原类型中的属性计算得来的:
type Double<T> = { [K in keyof T]: T[K] extends number ? T[K] * 2 : T[K]; }; interface Person { name: string; age: number; city: string; } type DoubledPerson = Double<Person>; // { name: string; age: number * 2; city: string; }
现在,我们可以使用
DoubledPerson
来创建一个新的对象,其中age
属性的值是原来的两倍:const doubledPerson: DoubledPerson = { name: "Alice", age: 25, city: "London", }; console.log(doubledPerson); // { name: "Alice", age: 50, city: "London" }
-
创建索引类型:
我们可以使用索引类型来创建新的类型,其中属性的名称是动态生成的:
type Indexable<T> = { [K in keyof T]: T[K]; }; interface Person { name: string; age: number; city: string; } type IndexablePerson = Indexable<Person>; // { [K in keyof Person]: Person[K]; }
现在,我们可以使用
IndexablePerson
来创建一个新的对象,其中属性的名称是Person
对象中属性的名称:const indexablePerson: IndexablePerson = { name: "Alice", age: 25, city: "London", }; console.log(indexablePerson.name); // "Alice" console.log(indexablePerson.age); // 25 console.log(indexablePerson.city); // "London"
这些只是 TypeScript 中类型操作的众多奇妙用法的几个例子。通过熟练掌握这些类型操作,我们可以编写出更灵活、更强大的代码。