1. Pick和Omit
源码地址
相似点:都是对接口进行剪裁
keyof 操作符常和接口结构一起使用,得到一组对象键值的字面量类型组成的联合类型,如 ‘a’|‘b’|‘c’。我们也常用 keyof any 表示成员未知的联合类型。
interface test {
a: string;
b: string;
c: number;
}
// { a:number; }
type OnlyA = Pick<Foo, "a">;
// { b: string; c: boolean}
type ExcludeA = Omit<Foo, "a">;
// Pick的实现
type Pick<T, P extends keyof T> = {
[P in T]: T[P]
}
// Omit
type Omit<T, P extends keyof any> = Pick<T, Exclude<keyof T, P>>
// Exclude
type Exclude<T, P> = T extends P ? never : T
2. keyof,in
keyof
keyof会取得接口的键值并且保存为联合类型
interface iUserInfo {
name: string;
age: number;
}
// keys = 'name' | 'age'
type keys = keyof iUserInfo;
// 希望获取传入对象中的属性值
function getValue(o: object, key: string) {
return o[key];
}
const obj1 = { name: '张三', age: 18 };
const name = getValue(obj1, 'name')
// 用TS进行改写
function getValue<T extends Object, P extends keyof T>(o: T, key: P): T[P] {
return o[key];
}
in
in主要用于取联合类型的值,主要用于数组和对象的构造。
但切记不要用于 interface,否则会出错
type name = 'firstName' | 'lastName';
type TName = {
[key in name]: string;
};
3. 索引类型,索引访问类型和映射类型
索引类型
我们也可以描述那些能够“通过索引得到”的类型,比如a[10]或ageMap[“daniel”]。 可索引类型具有一个 索引签名,它描述了对象索引的类型,还有相应的索引返回值类型。
interface StringArray {
[index: number]: string; //索引签名
}
let myArray: StringArray;
myArray = ["Bob", "Fred"];
let myStr: string = myArray[0];
索引签名
链接地址
当类型的属性的实际名称不知道,但它们将引用的数据类型是已知的时候,索引签名是很方便的。
一旦定义了任意属性,那么确定属性和可选属性的类型都必须是它的类型的子集
type User = {
name: string;
preferences: {
[key: string]: string;
}
};
const currentUser: User = {
name: 'Foo Bar',
preferences: {
lang: 'en',
},
};
const currentLang = currentUser.preferences.lang;
索引访问类型
type AppConfig = {
username: string;
layout: string;
};
// Username = string;
type Username = AppConfig["username"];
映射类型
TypeScript中的映射类型意味着我们通过对其每个属性应用转换,将一个类型转换为另一个类型。
链接地址
type Device = {
manufacturer: string;
price: number;
};
type DeviceFormatter = {
[key in keyof Device as `format${Capitalize<key>}`]: (value: Device[key]) => string
}
format${Capitalize<Key>} 是映射的转换部分,使用键重映射和模板字面类型将属性名称从x 改为formatX 。
TypeScript 团队发布了 TypeScript 4.1,其中包括功能强大的模板字面量类型、映射类型的键重映射以及递归条件类型。
4. type(类型别名)和interface(接口)
- 接口是通过继承的方式来扩展,类型别名是通过 & 来扩展。
- 同名接口可以自动合并,而类型别名不行。
- 可以用interface的时候尽量使用interface。
5. extends
除了自身的属性外,继承了其他接口的属性
6. typescript
https://juejin.cn/post/6981728323051192357
- any和unknown的区别
any和unknown都支持传入任何类型的函数
使用any表示完全放弃了类型检查,类似于纯JS的操作,而使用unknown时,会对一些错误操作抛出提示信息来提醒我们需要进行缩小范围的类型检查
unknown
function getDog() {
return '22'
}
const dog: unknown = getDog();
dog.hello(); //Object is of type 'unknown'
any
function getDog() {
return '22'
}
const dog: unknown = getDog();
dog.hello(); // 不会跑出任何类型错误提示
- 元组(tuple)
每一项数据必须对应
const str: [string, string, number] = ['test', 'test', 1];
- 联合类型,交叉类型
联合类型:变量可能是联合类型中的其中一种
交叉类型:变量是类型的合并(由于type无法实现interface那样的继承,所以使用交叉类型来进行多个type的合并)
interface Waiter {
anjiao: boolean;
say: () => {};
}
interface Teacher {
anjiao: boolean;
skill: () => {};
}
// 联合类型
function judgeWho(animal: Waiter | Teacher) {}
// 交叉类型
function judgeWho(jishi: Waiter & Teacher) {}
-
in,keyof
in用于对类型进行遍历或者判断是否存在于类型中
keyof用于将类型的键值组成联合类型 -
typeof
检测一个变量的类型
interface Hero {
name: string;
skill: string;
}
const zed: Hero = { name: "影流之主", skill: "影子" };
type LOL = typeof zed; // type LOL = Hero
- 工具类型
Partial<T>:将T中所有属性转化为可选属性
Required<T>:将T中所有属性转化为必填属性
export interface UserModel {
name: string;
age?: number;
sex: number;
}
type JUserModel = Partial<UserModel>
// =
type JUserModel = {
name?: string | undefined;
age?: number | undefined;
sex?: number | undefined;
}
// 源码
typeof Partial<T> = {[key in keyof T]?: T[key]}