TypeScript高级特性

更新日期: 2022-02-08阅读: 1.1k标签: TypeScript

Partial & Required

  • Partial 译为 部分的/局部的/不完全的, 作用是将一个接口的所有参数变为非必填
  • Required 译为必须的, 作用是将一个接口中所有非必填参数 变为必填,Required<T> 的作用就是将某个类型里的属性全部变为必选项。

ts中的声明

/**
* Make all properties in T optional
*/
type Partial<T> = {
[P in keyof T]?: T[P];
};

/**
* Make all properties in T required
*/
type Required<T> = {
[P in keyof T]-?: T[P];
};

Partial用法示例

type Person = {
name: string;
age: number;
}

// 直接使用初始化所有参数都是必填
let tom:Person = {
name: 'tom',
age: 20
};


// 使用Partial将Person中所有的参数变为非必填
type PartialPerson = Partial<Person>;

let partialPerson: PartialPerson = {
name: 'tom'
};

特殊的情况

type Person = {
name: string;
age: number;
contact: {
email: string;
phone: number;
wechat: string;
}
}

type PartialPerson = Partial<Person>;

// 可以看出来 第一层属性都变成了非必填 第二层都没变
let partialPerson: PartialPerson = {
name: 'tom',
contact: { // error
email: 'goodboyb@qq.com'
}
};


// 再来看看ts内部类型的定义
/**
* Make all properties in T optional
*/
type Partial<T> = {
[P in keyof T]?: T[P];
};
// 可以看出来并没有考虑内层


// 稍微改造一下
/**
* Make all properties in T optional
*/
type DeepPartial<T> = {
[P in keyof T]?: T[P] extends Object ? DeepPartial<T[P]> : T[P];
}

// 现在针对那种特殊情况就能处理了

Required 用法示例

interface User {
id: number;
age: number;
}
type PartialUser = Partial<User>;
// type PartialUser = {
// id?: number;
// age?: number;
// }
type PickUser = Required<PartialUser>;
// type PickUser = {
// id: number;
// age: number;
// }

Record

Record 译为 记录/记载, 作用是将一个类型的所有属性值都映射到另一个类型上并创造一个新的类型

ts中的声明

/**
* Construct a type with a set of properties K of type T
*/
type Record<K extends keyof any, T> = {
[P in K]: T;
};

看类型的定义就可以看出来,将K中的每个属性([P in K]),都转为T类型, K可以是联合类型、对象、枚举…

type petsGroup = 'dog' | 'cat' | 'fish';

type numOrStr = number | string;

type IPets = Record<petsGroup, numOrStr>;

// type IPets = {
// dog: numOrStr;
// cat: numOrStr;
// fish: numOrStr;
// }

Pick

Pick译为挑选/选择, 作用是从一个复合类型中,取出几个想要的类型的组合一个新的类型

ts中的声明

/**
* From T, pick a set of properties whose keys are in the union K
*/
type Pick<T, K extends keyof T> = {
[P in K]: T[P];
};

K extends keyof T的作用是约束K的key在T的key中,不能超出这个范围,否则会报错的

keyof

  • keyof 用于获取某种类型的所有键,其返回类型是联合类型
// keyof 用于获取某种类型的所有键,其返回类型是联合类型
interface B {
id: number;
name: string;
age: number;
}

type B1 = keyof B;
// type B1 = "id" | "name" | "age"

extends

这里的extends并不是用来继承的, 而是用来限制类型

// 对象extends
type T = {
id: number;
name: string;
}

type K = {
id: number;
}
type IType = K extends T ? K : T;
// type IType = {
// id: number;
// name: string;
// }
// 此处 K extends T 限制K中必须有T的所有属性, 通俗点说就是T必须是K的子集


// 联合类型extends
type T = "id" | "name";
type K = "id";
type IType = K extends T ? K : T;
// type IType = "id"
// 此处限制为K必须包含于T,通俗点说就是K是T的子集

使用Pick挑选属性组成新的类型

interface B {
id: number;
name: string;
age: number;
}

type PickB = Pick<B, "id" | "name">;

// type PickB = {
// id: number;
// name: string;
// }

Exclude

Exclude 译为排除/不包括, Exclude<T, U> 表示从T中排除那些可分配给U的类型, 简单点说就是将 T 中某些属于 U 的类型移除掉。也可理解为取补集

ts中的声明

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

// 例子1
type T = {
name: string
age: number
}

type U = {
name: string
}

type IType = Exclude<keyof T, keyof U>
// type IType = "age"

type T0 = Exclude<"a" | "b" | "c", "a" | "b">
// type T0 = "c"
type T1 = Exclude<"a" | "b" | "c", "a" | "b" | 's'>
// type T1 = "c"

Extract

Extract 译为提取, Extract<T, U>从T中提取那些可分配给U的类型, 简单点说就是提取T中,U也有的元素,也可理解为取交集

ts中的定义

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

type T0 = Extract<"a" | "b" | "c", "a" | "f">
// type T0 = "a"

type T = {
name: string
age: number
}

type U = {
name: string
}

type IType = Extract<keyof T, keyof U>
// type IType = "name"

ConstructorParameters

ConstructorParameters 译为构造函数参数, 获取元组中构造函数类型的参数

ts中的声明

/**
* Obtain the parameters of a constructor function type in a tuple
*/
type ConstructorParameters<T extends new (...args: any) => any> = T extends new (...args: infer P) => any ? P : never;

可以用来获取类的参数类型组成的元组类型

class People {
name: string
age: number

constructor(name: string) {
this.name = name;
}
}


type IType = ConstructorParameters<typeof People>
// type IType = [name: string]
// 注意这里typeof操作是取类型的作用

infer

表示在 extends 条件语句中待推断的类型变量

// 例子1
// 若T是Array类型,则返回T的泛型,否则返回never类型
type Union<T> = T extends Array<infer U> ? U: never

type a = {
name: string
}

type b = string[]


type c = Union<b>
// type c = string
type d = Union<a>
// type d = never


// 例子2
// 若T满足(param: infer P) => any,则返回函数入参的类型,否则直接返回T
type ParamType<T> = T extends (param: infer P) => any ? P: T;

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

type Func = (dog:IDog) => void;

type Param = ParamType<Func>; // IDog
type TypeString = ParamType<string> //string

理解了infer 我们在回来看ts中ConstructorParameters 的声明

type ConstructorParameters<T extends new (...args: any) => any> = T extends new (...args: infer P) => any ? P : never;

// T extends new (...args: any) => any 首先给T加了个约束 必须满足new (...args: any) => any 也就是说T必须是构造函数类型

// T extends new (...args: infer P) => any ? P : never
// T若满足new (...args: any) => any 则返回所有入参的类型, 否则返回never

InstanceType

InstanceType 译为实例类型, 用来获取构造函数的返回类型

ts中的定义

/**
* Obtain the return type of a constructor function type
*/
type InstanceType<T extends new (...args: any) => any> = T extends new (...args: any) => infer R ? R : any;

class People {
name: string
age: number

constructor(name: string) {
this.name = name;
}
}

type IType = InstanceType<typeof People>
// type IType = People
// 因为constructor默认返回this
// constructor People(name: string): People

NonNullable

NonNullable 译为不可为空, NonNullable<T>从T中排除null和undefined

ts 中的定义

/**
* Exclude null and undefined from T
*/
type NonNullable<T> = T extends null | undefined ? never : T;

type example = NonNullable<string | number | undefined>
// type example = string | number

Parameters & ReturnType

  • Parameters 用来获取函数参数的类型
  • ReturnType 用来获取函数返回值类型

ts中的定义

/**
* Obtain the parameters of a function type in a tuple
*/
type Parameters<T extends (...args: any) => any> = T extends (...args: infer P) => any ? P : never;

/**
* Obtain the return type of a function type
*/
type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;

定义时写的很明确,不过多赘述

type IFoo = (
uname: string,
uage: number
) => {
name: string;
age: number;
};
//参数类型
type Ibar = Parameters<IFoo>;
// type Ibar = [uname: string, uage: number]
type T0 = ReturnType<IFoo>;
// type T0 = {
// name: string;
// age: number;
// }

readonly & ReadonlyArray

  • readonly 只读 被readonly 标记的属性只能在声明时或类的构造函数中赋值,之后将不可改(即只读属性)。
  • ReadonlyArray 同理, 只读数组
interface ReadonlyArray<T> {
/** Iterator of values in the array. */
[Symbol.iterator](): IterableIterator<T>;

/**
* Returns an iterable of key, value pairs for every entry in the array
*/
entries(): IterableIterator<[number, T]>;

/**
* Returns an iterable of keys in the array
*/
keys(): IterableIterator<number>;

/**
* Returns an iterable of values in the array
*/
values(): IterableIterator<T>;
}

interface Person {
readonly id: number;
}
const data: Person = {
id: 456,
};

data.id = 789;
// 无法分配到 "id" ,因为它是只读属性。ts(2540)

const arr: number[] = [1, 2, 3, 4];

let ro: ReadonlyArray<number> = arr;

ro.push(444);
// 类型“readonly number[]”上不存在属性“push”。ts(2339)

总结

ts中有很多特性都可以在lib.es5.ts中去查看, 里面定义的接口和类型非常多,主要是理解ts定义的套路,就能举一反三

来自:https://mp.weixin.qq.com/s/nDqwj3r1HOODYQik8F6iQg

链接: https://fly63.com/article/detial/11127

用TypeScript弥补Elm和JavaScript之间的差距

近些日子,我使用了新语言编程,从JavaScript,切确地说是Elm,转成TypeScript。在本文中,我将继续深挖一些我非常喜欢的TypeScript特性。

Typescript 和 Javascript之间的区别

TypeScript 和 JavaScript 是目前项目开发中较为流行的两种脚本语言,我们已经熟知 TypeScript 是 JavaScript 的一个超集,但是 TypeScript 与 JavaScript 之间又有什么样的区别呢?

Nerv_一款类 React 前端框架,基于虚拟 DOM 技术的 JavaScript(TypeScript) 库

Nerv_是一款由京东凹凸实验室打造的类 React 前端框架,基于虚拟 DOM 技术的 JavaScript(TypeScript) 库。它基于React标准,提供了与 React 16 一致的使用方式与 API。

TypeScript_TS系列之高级类型

交叉类型:将多个类型合并为一个类型、联合类型:表示取值可以为多种类型中的一种、混合类型:一个例子就是,一个对象可以同时做为函数和对象使用,并带有额外的属性、类型断言:可以用来手动指定一个值的类型

TypeScript 在 JavaScript 的基础上的改动

在做比较大的,多人合作的项目的时候,TypeScript会更加地适合,这得益于它的可读性,面向对象性以及易于重构的特点。但如果只是自己做小程序,不需要太多人参与的时候,JavaScript则会更加简单。

5分钟了解TypeScript

有两种方式安装TypeScript,如何创建第一个TypeScript文件,在TypeScript中,可以使用interface来描述一个对象有firstName和lastName两个属性,TypeScript支持JavaScript的新功能,其中很重要的一个功能就是基于类的面向对象编程

如何编写 Typescript 声明文件

使用TypeScript已经有了一段时间,这的确是一个好东西,虽说在使用的过程中也发现了一些bug,不过都是些小问题,所以整体体验还是很不错的。有关TypeScript声明类型声明相关的目前就总结了这些比较常用的

谷歌为何会选用TypeScript?

谷歌在很早之前就张开双臂拥抱 Web 应用程序,Gmail 已经发布 14 年了。当时,JavaScript 的世界是疯狂的。Gmail 工程师不得不为 IE 糟糕的垃圾回收算法捏一把汗,他们需要手动将字符串文字从 for 循环中提取出来,以避免 GC 停顿

为什么要学习Typescript 语言呢?Typescript 开发环境安装

TypeScript是一种由微软开发的自由和开源的编程语言。它是JavaScript的一个超集,TypeScript是JavaScript类型的超集,它可以编译成纯JavaScript。TypeScript可以在任何浏览器、任何计算机和任何操作系统上运行,并且是开源的。

使用TypeScript两年后-值得吗?

差不多两年前,我在一个创业团队中开始了一个全新的项目。用到的全都是类似Microservices,docker,react,redux这些时髦的东西。我在前端技术方面积累了一些类似的经验

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!