typescript 的一些其他用法

507 阅读6分钟

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要两个参数,Omit<type,string>: 参数:第一个为继承的type类型,第二个为想要去掉的key的字符串,多个字符串用|分开 使用也很简单: 去除单个,原始类型为联系人列表,新数据数据为没有邮箱项的联系人列表

export type OmitEmailContact = Omit<Contact, 'email' >;
OmitEmailContact{
  name: string;
  phone?: string; 
  avatar: string;
  userid: string;
}

image.png

pick

From T, pick a set of properties whose keys are in the union K

其实就是在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; 
}

typeof

在js语法中,typeof是获取类型,在ts中的应用则像将js语法转成ts语法

如下demo中A相当于type A = { x: number; y: number; }

const obj = { x: 10, y: 3 }
type A = typeof obj;
const a: A = {
    x:1,
    y:1
}
复制代码

与ReturnType的结合:

function f() {
  return { x: 10, y: 3 };
}
type P = ReturnType<typeof f>; //type P = { x: number; y: number; }

keyof

keyof运算符

keyof诞生于TypeScript2.1版本,它的作用是:帮助我们获取某种类型的所有键,返回的是一个联合类型。 s 我们可以看一个很常见的示例:

function getProperty<T, K extends keyof T>(obj: T, key: K) {
  return obj[key]; // Inferred type is T[K]
}

function setProperty<T, K extends keyof T>(obj: T, key: K, value: T[K]) {
  obj[key] = value;
}

Exclude

用法:Exclude<Type, ExcludedUnion>。简单理解Exclude就是数学集合中找出Type的“差集”,就是将类型A与B对比,返回A中独有的类型。

看一个示例:

\

那么大家肯定也会好奇Exclude背后的定义是怎么样的。

/**
 * Exclude from T those types that are assignable to U
 */
type Exclude<T, U> = T extends U ? never : T;

Extends

T extends U ? never : T这里的extends可与class的extends不是一回事,这里指的是条件类型。

这里不做过多的扩展,重点通过一个概念分布式条件类型来理解上面Exclude的写法。

type A = 'a' | 'b' | 'c';
type B = 'a';

type C = Exclude<A, B>; // 'b' | 'c';

// A extends B ? never : A 等价于 ('a' | 'b' | 'c') extends B ? never : ('a' | 'b' | 'c') 等价于如下
type D = ('a' extends B ? never : 'a') | ('b' extends B ? never : 'b') | ('c' extends B 

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
}

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
}

keyof typeof 同时使用

你可能已经知道,typeof 运算符为你提供对象的类型,上面例子中 Person interface,我们已经知道它的类型,所以我们只需要在 Person 上使用 keyof 操作符。

但是,当我们不知道对象的类型,或者我们只有一个值,类似于下面的情况,应该怎么办呢?

const bmw = { name: "BMW", power: "1000hp" }

这就是我们需要一起使用 keyof typeof 的地方。

typeof bmw 给到你他们的类型 { name: string, power: string }

接着 keyof 操作符给到你联合字面量类型,像下面代码描述的一样:

type CarLiteralType = keyof typeof bmw

let carPropertyLiteral: CarLiteralType
carPropertyLiteral = "name"       // OK
carPropertyLiteral = "power"      // OK
carPropertyLiteral = "anyOther"   // Error...Type '"anyOther"' is not assignable to type '"name" | "power"'

enum 上使用 keyof typeof

在 Typescript 中,enum 在编译时被用作类型,用来实现常量的类型安全,但是它们在运行时被视为对象。这是因为,当 Typescript 代码被编译为 Javascript 时,它们会被转换为普通对象。接着我们回顾一下,最开始我们提出问题的例子是这样的:

enum ColorsEnum {
    white = '#ffffff',
    black = '#000000',
}

这里 ColorsEnum 在运行时作为一个对象存在,不是一个类型,所以,我们需要一起使用 keyof typeof 这两个操作符,像下面代码展示的一样。

type Colors = keyof typeof ColorsEnum

let colorLiteral: Colors
colorLiteral = "white"  // OK
colorLiteral = "black"  // OK
colorLiteral = "red"    // Error...Type '"red"' is not assignable to type '"white" | "black"'

as const

使用 as const 定义一个对象而且对象的类型是常数的话,可以使用,否则Z.lock :string

const Z = {
  lock: 5,
  header: 15,
  footer: 10,
  lockShadow: 20,
  scrollItem: 30,
  loadingIndicator: 40,
} as const

image.png

NonNullable<T>

去除T中的 null 和 undefined 类型

Parameters<T>

返回类型为T的函数的参数类型所组成的数组


type T0 = Parameters<() => string>;  // []

type T1 = Parameters<(s: string) => void>;  // [st

Record

以 typeof 格式快速创建一个类型,此类型包含一组指定的属性且都是必填。

type Coord = Record<'x' | 'y', number>;

// 等同于
type Coord = {
	x: number;
	y: number;
}

InstanceType<T>

返回构造函数类型T的实例类型

class C {
  x = 0;
  y = 0;
}

type T0 = InstanceType<typeof C>;  // C

ReturnType<T>

function T的返回类型

type T0 = ReturnType<() => string>;  // string

type T1 = ReturnType<(s: string) => void>;  // void

type Predicate = (x: unknown) => boolean;

type K = ReturnType<Predicate>;

 // type K = boolean
function f() {

return { x: 10, y: 3 };

}

type P = ReturnType<typeof f>;


type P = { x: number; y: number; }

image.png

image.png

image.png

image.png

image.png

image.png

根据对象value去获取key

image.png

参考库: github.com/type-challe…

Record<K,T>

构造一个类型,该类型具有一组属性K,每个属性的类型为T。可用于将一个类型的属性映射为另一个类型。Record 后面的泛型就是对象键和值的类型。

简单理解:K对应对应的key,T对应对象的value,返回的就是一个声明好的对象

type TodoProperty = 'title' | 'description';

type Todo = Record<TodoProperty, string>;
// =
type Todo = {
    title: string;
    description: string;
}

interface IGirl {
  name: string;
  age: number;
}

type allGirls = Record<string, IGirl>

Abstract

1、什么是抽象类

Abstract classes are base classes from which other classes may be derived. They may not be instantiated directly. Unlike an interface, an abstract class may contain implementation details for its members. Theabstractkeyword is used to define abstract classes as well as abstract methods within an abstract class.

抽象类是可以派生其他类的基类。它不能被直接实例化。与接口不同,一个抽象类可以包含它的成员的实现细节。abstract 关键字是用来定义抽象类的,同时也是定义它内部的抽象方法的。

2、定义一个抽象类

  • 抽象类用abstract关键字修饰
  • 抽象类其实就是将通用性的东西抽离出来,变成一个抽象类
  • 抽象类可以定义属性、方法和抽象方法
  • 抽象类只能被继承,不能被实例化
  • 抽象类可以有构造器

3、接口

  • 接口不能被直接实例化
  • 接口不包括具体的实现
  • 接口不能有构造器

4、抽象类和接口的区别

相同点:

  • 抽象类和接口都不能被直接实例化

不同点:

  • 抽象类里面有方法的实现,而接口不存在方法的实现
  • 抽象类可以有构造器 constructor,而接口没有构造器 constructor
  • 抽象类可以是 public、protected,而接口只能是 public
  • 抽象类当父类被继承,且抽象类的派生类的构造函数中必须执行super(),而接口可以当做子类继承其他接口

type

image.png

Differences Between Type Aliases and Interfaces

Type aliases and interfaces are very similar, and in many cases you can choose between them freely. Almost all features of an interface are available in type, the key distinction is that a type cannot be re-opened to add new properties vs an interface which is always extendable.

image.png

image.png

image.png

参考: blog.csdn.net/jojo1001/ar…

juejin.cn/post/685457…

zhuanlan.zhihu.com/p/397398407…

juejin.cn/post/702323…

juejin.cn/post/703262…

juejin.cn/post/698172…