ts(TypeScript)常用语法
比如有一个联系人列表
export interface Contact{
name: string; // 姓名
phone?: string; // 手机号
email: string; // 邮箱
avatar: string; // 头像
userid: string; // id
}
1.Omit去除类型中某些项(官方提供)
现在需要定义一个新的数据类型,新的联系人列表没有邮箱项
可以使用Omit,其源码如下
/**
* Construct a type with the properties of T except for those in type K.
*/
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
Omit会构造一个除类型K外具有T性质的类型
可以看出需Omit要两个参数,Omit<type,string>:
参数:第一个为继承的type类型,第二个为想要的key的字符串,多个字符串用|分开
使用也很简单:
去除单个,原始类型为联系人列表,新数据数据为没有邮箱项的联系人列表
export type OmitEmailContact = Omit<Contact, 'email' >;
OmitEmailContact{
name: string;
phone?: string;
avatar: string;
userid: string;
}
去除多个,原始类型为联系人列表,新数据数据为没有邮箱项与头像的联系人列表
export type OmitEmailAvatarContact = Omit<Contact, 'email' | 'avatar'>;
OmitEmailAvatarContact {
name: string;
phone?: string;
userid: string;
}
2.Pick选取类型中指定类型(官方提供)
现在联系人列表只要姓名电话即可
从T中选择一组属性,将它们在K中联合
type Pick<T, K extends keyof T> = {
[P in K]: T[P];
};
使用如下
export interface ContactPick extends Pick<Contact, 'name' | 'phone'> {}
ContactPick {
name: string;
phone?: string;
}
3.给类型加上指定类型(自定义)
已经定义好了数据类型,现在需要给其中一些加上id这个类型
export type WithId<T, P = string> = T & { id: P };
使用如下
export interface ContactWithId = WithId<Contact>
4.Partial将类型中所有选项变为可选,即加上?(官方提供)
可以使用Partial,其源码如下
/**
* Make all properties in T optional
*/
type Partial<T> = {
[P in keyof T]?: T[P];
};
使用如下
export interface PartialContact= Partial<Contact>
PartialContact{
name?: string; // 姓名
phone?: string; // 手机号
email?: string; // 邮箱
avatar?: string; // 头像
userid?: string; // id
}
5.Required将类型中所有选项变为必选,去除所有?(官方提供)
可以使用Required,其源码如下
/**
* Make all properties in T required
*/
type Required<T> = {
[P in keyof T]-?: T[P];
};
使用如下
export interface RequiredContact= Required<Contact>
RequiredContact{
name: string; // 姓名
phone: string; // 手机号
email: string; // 邮箱
avatar: string; // 头像
userid: string; // id
}
何为Pick?
type Pick<T, K extends keyof T> = {
[key in K]: T[key]
}
就是从一个复合类型中,取出几个想要的类型的组合,例如:
// 原始类型
interface TState {
name: string;
age: number;
like: string[];
}
// 如果我只想要name和age怎么办,最粗暴的就是直接再定义一个(我之前就是这么搞得)
interface TSingleState {
name: string;
age: number;
}
// 这样的弊端是什么?就是在Tstate发生改变的时候,TSingleState并不会跟着一起改变,所以应该这么写
interface TSingleState extends Pick<TState, "name" | "age"> {};
写到这里,Pick的用法就写完了,但是会有个疑问,extends不是用来继承的么?那为什么可以写在泛型里?有没有人跟我一样的疑惑?
我去查了资料后发现,还是官方文档中有这个解释(所以还是要多看文档,官方文档大多数比外面写的好得多),以下这段内容来自于官方文档。
泛型约束《官方文档传送门》
你应该会记得之前的一个例子,我们有时候想操作某类型的一组值,并且我们知道这组值具有什么样的属性。 在 loggingIdentity例子中,我们想访问arg的length属性,但是编译器并不能证明每种类型都有length属性,所以就报错了。
function loggingIdentity<T>(arg: T): T {
console.log(arg.length); // Error: T doesn't have .length
return arg;
}
相比于操作any所有类型,我们想要限制函数去处理任意带有.length属性的所有类型。 只要传入的类型有这个属性,我们就允许,就是说至少包含这一属性。 为此,我们需要列出对于T的约束要求。
为此,我们定义一个接口来描述约束条件。 创建一个包含 .length属性的接口,使用这个接口和extends关键字来实现约束:
interface Lengthwise {
length: number;
}
function loggingIdentity<T extends Lengthwise>(arg: T): T {
console.log(arg.length); // Now we know it has a .length property, so no more error
return arg;
}
现在这个泛型函数被定义了约束,因此它不再是适用于任意类型:
loggingIdentity(3); // Error, number doesn't have a .length property
我们需要传入符合约束类型的值,必须包含必须的属性:
loggingIdentity({length: 10, value: 3});
在泛型约束中使用类型参数
你可以声明一个类型参数,且它被另一个类型参数所约束。 比如,现在我们想要用属性名从对象里获取这个属性。 并且我们想要确保这个属性存在于对象 obj
上,因此我们需要在这两个类型之间使用约束。
function getProperty(obj: T, key: K) {
return obj[key];
}
let x = { a: 1, b: 2, c: 3, d: 4 };
getProperty(x, "a"); // okay
getProperty(x, "m"); // error: Argument of type 'm' isn't assignable to 'a' | 'b' | 'c' | 'd'.
在泛型里使用类类型
在TypeScript使用泛型创建工厂函数时,需要引用构造函数的类类型。比如,
function create<T>(c: {new(): T; }): T {
return new c();
}
一个更高级的例子,使用原型属性推断并约束构造函数与类实例的关系。
class BeeKeeper {
hasMask: boolean;
}
class ZooKeeper {
nametag: string;
}
class Animal {
numLegs: number;
}
class Bee extends Animal {
keeper: BeeKeeper;
}
class Lion extends Animal {
keeper: ZooKeeper;
}
function createInstance<A extends Animal>(c: new () => A): A {
return new c();
}
createInstance(Lion).keeper.nametag; // typechecks!
createInstance(Bee).keeper.hasMask; // typechecks!
function getProperty(obj:T,key:K){
return obj[key];
}
let x={a:1,b:2,c:3,d:4}