关闭

TypeScript 高级类型总结

时间: 2021-01-05阅读: 154标签: TypeScript

TypeScript 是一种类型化的语言,允许你指定变量、函数参数、返回的值和对象属性的类型。

以下是 TypeScript 高级类型的使用方法总结,而且带有例子。

Intersection 类型

Intersection 类型是一种把对多种类型进行组合的方法。这意味着你可以把给定的多种类型合并,并得到一个带有全部属性的新类型。

type LeftType = {
  id: number
  left: string
}

type RightType = {
  id: number
  right: string
}

type IntersectionType = LeftType & RightType

function showType(args: IntersectionType) {
  console.log(args)
}

showType({ id: 1, left: "test", right: "test" })
// Output: {id: 1, left: "test", right: "test"}

代码中的 IntersectionType ”组合了两种类型: LeftType 和 RightType,并使用 & 符号来构造交 intersection 类型。

Union 类型

Union 类型用来在给定变量中使用不同类型的注释。

type UnionType = string | number

function showType(arg: UnionType) {
  console.log(arg)
}

showType("test")
// Output: test

showType(7)
// Output: 7

showType 函数是一个 union 类型,它能够接受字符串和数字作为参数。

范型类型

泛型类型是一种用来重用给定类型的一部分的方式。它用来处理参数传入的类型 T。

function showType<T>(args: T) {
  console.log(args)
}

showType("test")
// Output: "test"

showType(1)
// Output: 1

要构造一个泛型类型,需要用到尖括号并将 T 作为参数进行传递。

在下面的代码中,我用的是 T(这个名称随你决定)这个名字,然后使用不同的类型注释调用了两次 showType 函数,因为它是可以重用的。

interface GenericType<T> {
  id: number
  name: T
}

function showType(args: GenericType<string>) {
  console.log(args)
}

showType({ id: 1, name: "test" })
// Output: {id: 1, name: "test"}

function showTypeTwo(args: GenericType<number>) {
  console.log(args)
}

showTypeTwo({ id: 1, name: 4 })
// Output: {id: 1, name: 4}

还有另一个例子,例子中有一个接口 GenericType,这个接口接收通用类型 T。由于它是可重用的,因此我们可以用字符串和数字来调用它。

interface GenericType<T, U> {
  id: T
  name: U
}

function showType(args: GenericType<number, string>) {
  console.log(args)
}

showType({ id: 1, name: "test" })
// Output: {id: 1, name: "test"}

function showTypeTwo(args: GenericType<string, string[]>) {
  console.log(args)
}

showTypeTwo({ id: "001", name: ["This", "is", "a", "Test"] })
// Output: {id: "001", name: Array["This", "is", "a", "Test"]}

泛型类型可以接收多个参数。在例子中传入两个参数:T 和 U,然后将它们用作属性的类型注释。也就是说,我们现在可以给这个该接口并提供两个不同的类型作为参数。

实用工具类型

TypeScript 提供了方便的内置实用工具,可帮助我们轻松地操作类型。在使用时需要将要处理的类型传递给 <>。

Partial

  • Partial<T>

Partial 允许你将所有类型为 T 的属性设为可选。它将在每个字段旁边添加一个 ? 标记。

interface PartialType {
  id: number
  firstName: string
  lastName: string
}

function showType(args: Partial<PartialType>) {
  console.log(args)
}

showType({ id: 1 })
// Output: {id: 1}

showType({ firstName: "John", lastName: "Doe" })
// Output: {firstName: "John", lastName: "Doe"}

代码中有一个名为 PartialType 的接口,它作为函数 showType() 的参数的类型注释。要想使属性是可选的,必须用到 Partial 关键字,并传入 PartialType 类型作为参数。现在所有字段都变成了可选的。

Required

  • Required<T>

与 Partial 不同,Required 使所有类型为 T 的属性成为必需的。

interface RequiredType {
  id: number
  firstName?: string
  lastName?: string
}

function showType(args: Required<RequiredType>) {
  console.log(args)
}

showType({ id: 1, firstName: "John", lastName: "Doe" })
// Output: { id: 1, firstName: "John", lastName: "Doe" }

showType({ id: 1 })
// Error: Type '{ id: number: }' is missing the following properties from type 'Required<RequiredType>': firstName, lastName

即使在之前先将它们设为可选的,Required 也会使所有符合条件的属性成为必需的。而且如果省略掉属性的话TypeScript 将会引发错误。

Readonly

  • Readonly<T>

这个类型会对所有类型为 T 的属性进行转换,使它们无法被重新赋值。

interface ReadonlyType {
  id: number
  name: string
}

function showType(args: Readonly<ReadonlyType>) {
  args.id = 4
  console.log(args)
}

showType({ id: 1, name: "Doe" })
// Error: 无法给'id'重新赋值,因为它是只读属性。

在代码中用 Readonly 来使 ReadonlyType 的属性不可被重新赋值。如果你一定要为这些字段赋值的话,将会引发错误。

Besides that, you can also use the keyword readonly in front of a property to make it not reassignable.
除此之外,还可以在属性前面使用关键字“ readonly”,以使其无法重新分配。

interface ReadonlyType {
  readonly id: number
  name: string
}

Pick

  • Pick<T, K>

它允许你通过选择某个类型的属性 k ,从现有的模型 T 中创建一个新类型。

interface PickType {
  id: number
  firstName: string
  lastName: string
}

function showType(args: Pick<PickType, "firstName" | "lastName">) {
  console.log(args)
}

showType({ firstName: "John", lastName: "Doe" })
// Output: {firstName: "John"}

showType({ id: 3 })
// Error: Object literal may only specify known properties, and 'id' does not exist in type 'Pick<PickType, "firstName" | "lastName">'

Pick 与前面看到的那些有点不同。它需要两个参数 —— T 是要从中选择元素的类型,k 是要选择的属性。还可以通用管道符号 (|)将它们分开来选择多个字段。

Omit

  • Omit<T, K>

Omit 与Pick 相反。它从类型 T 中删除 K 属性。

interface PickType {
  id: number
  firstName: string
  lastName: string
}

function showType(args: Omit<PickType, "firstName" | "lastName">) {
  console.log(args)
}

showType({ id: 7 })
// Output: {id: 7}

showType({ firstName: "John" })
// Error: Object literal may only specify known properties, and 'firstName' does not exist in type 'Pick<PickType, "id">'

Omit 的工作方式与 Pick 类似。

Extract

  • Extract<T, U>

Extract 使你通过选择出现在两个不同类型中的属性来构造类型。它从 T 中提取所有可分配给 U 的属性。

interface FirstType {
  id: number
  firstName: string
  lastName: string
}

interface SecondType {
  id: number
  address: string
  city: string
}

type ExtractType = Extract<keyof FirstType, keyof SecondType>
// Output: "id"

在代码中的两个接口里有共有的属性 id。通过 Extract 可以把 id 提取出来。如果你有多个共享字段,Extract 将会提取所有相似的属性。

Exclude

与 Extract 不同,Exclude 通过排除已经存在于两个不同类型中的属性来构造类型。它排除了所有可以分配给 U 的字段。

interface FirstType {
  id: number
  firstName: string
  lastName: string
}

interface SecondType {
  id: number
  address: string
  city: string
}

type ExcludeType = Exclude<keyof FirstType, keyof SecondType>

// Output; "firstName" | "lastName"

在上面的代码中,属性 firstName 和 lastName 可分配给 SecondType 类型,因为它们在那里不存在。通过 Extract 可以按预期返回这些字段。

Record

  • Record<K,T>

Record 可以帮你构造一个类型,该类型具有给定类型 T 的一组属性 K。当把一个类型的属性映射到另一个类型时,用 Record 非常方便。

interface EmployeeType {
  id: number
  fullname: string
  role: string
}

let employees: Record<number, EmployeeType> = {
  0: { id: 1, fullname: "John Doe", role: "Designer" },
  1: { id: 2, fullname: "Ibrahima Fall", role: "Developer" },
  2: { id: 3, fullname: "Sara Duckson", role: "Developer" },
}

// 0: { id: 1, fullname: "John Doe", role: "Designer" },
// 1: { id: 2, fullname: "Ibrahima Fall", role: "Developer" },
// 2: { id: 3, fullname: "Sara Duckson", role: "Developer" }

Record 的工作方式相对简单。在代码中,它期望用 number 作为类型,这就是我们把 0、1 和 2 作为 employees 变量的键的原因。如果试图将字符串用作属性,则会引发错误。接下来,属性集由 EmployeeType 给出,因此该对象具有字段 id、 fullName 和 role。

NonNullable

  • NonNullable<T>

它允许你从类型 T 中删除 null 和 undefined。

type NonNullableType = string | number | null | undefined

function showType(args: NonNullable<NonNullableType>) {
  console.log(args)
}

showType("test")
// Output: "test"

showType(1)
// Output: 1

showType(null)
// Error: Argument of type 'null' is not assignable to parameter of type 'string | number'.

showType(undefined)
// Error: Argument of type 'undefined' is not assignable to parameter of type 'string | number'.

在代码中吧 NonNullableType 作为参数传给了 NonNullable,NonNullable 通过从该类型中排除 null 和 undefined 来构造新类型。也就是说,如果你传递可空的值,TypeScript 将会引发错误。

顺便说一句,如果把 --strictNullChecks 标志添加到 tsconfig 文件,TypeScript 将应用非空性规则。

映射类型

映射类型允许你获取现有模型并将其每个属性转换为新类型。注意,前面介绍的一些实用工具类型也是映射类型。

type StringMap<T> = {
  [P in keyof T]: string
}

function showType(arg: StringMap<{ id: number; name: string }>) {
  console.log(arg)
}

showType({ id: 1, name: "Test" })
// Error: Type 'number' is not assignable to type 'string'.

showType({ id: "testId", name: "This is a Test" })
// Output: {id: "testId", name: "This is a Test"}

StringMap<> 会将传入的任何类型转换为字符串。也就是说,如果在函数 showType() 中使用它,那么接收到的参数必须是字符串,否则 TypeScript 将会报错。

类型保护

类型保护使你可以用运算符检查变量或对象的类型。它实际上是一个检查用 typeof、instanceof 或 in 所返回类型的条件块。

  • typeof
function showType(x: number | string) {
  if (typeof x === "number") {
    return `The result is ${x + x}`
  }
  throw new Error(`This operation can't be done on a ${typeof x}`)
}

showType("I'm not a number")
// Error: This operation can't be done on a string

showType(7)
// Output: The result is 14

代码中有一个普通的 JavaScript 条件块,该块检查通过 typeof 检测到的参数的类型。在这种情况下就保护你的类型了。

  • instanceof
class Foo {
  bar() {
    return "Hello World"
  }
}

class Bar {
  baz = "123"
}

function showType(arg: Foo | Bar) {
  if (arg instanceof Foo) {
    console.log(arg.bar())
    return arg.bar()
  }

  throw new Error("The type is not supported")
}

showType(new Foo())
// Output: Hello World

showType(new Bar())
// Error: The type is not supported

和像前面的例子一样,这也是一个类型保护,它检查接收到的参数是否为 Foo 类的一部分,并对其进行处理。

  • in
interface FirstType {
  x: number
}
interface SecondType {
  y: string
}

function showType(arg: FirstType | SecondType) {
  if ("x" in arg) {
    console.log(`The property ${arg.x} exists`)
    return `The property ${arg.x} exists`
  }
  throw new Error("This type is not expected")
}

showType({ x: 7 })
// Output: The property 7 exists

showType({ y: "ccc" })
// Error: This type is not expected

在代码中,in 运算符用来检查对象上是否存在属性 x。

Conditional 类型

用来对两种类型进行测试,并根据测试的结果选择其中的一种。

type NonNullable<T> = T extends null | undefined ? never : T

这个例子中的 NonNullable 检查该类型是否为 null 并根据该类型进行处理。

    站长推荐

    1.云服务推荐: 国内主流云服务商,各类云产品的最新活动,优惠券领取。地址:阿里云腾讯云华为云

    2.广告联盟: 整理了目前主流的广告联盟平台,如果你有流量,可以作为参考选择适合你的平台点击进入

    链接: http://www.fly63.com/article/detial/10045

    关闭

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

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

    TypeScript:入门TS

    官方网站的定义是:TypeScript 是 JS 类型的超集。它假设咱们知道什么是超集,什么是类型化。为了简单起见,你可以将 TypeScript 看作是 JavaScript 之上的一个外壳。TypeScript 是一个外壳,因为编写 TypeScript 的代码

    TypeScript 渐进迁移指南

    最大的问题是我没有提供迁移大型项目的解决方案。显然,大型项目不可能在短时间内重写一切。因此,我很想分享下我最近学到的迁移项目到 TypeScript 的主要经验。

    为什么程序员如此热爱TypeScript ?

    Python 是我的谋生工具,我很喜欢它。尽管我对这门语言有一些 批评的地方,但我还是强烈推荐给任何开始从事数据科学的人。反正在这个领域中,比较有经验的人往往都是 Python 的布道师。

    放弃 TypeScript 的 7 个非常好的理由

    很多人都喜欢 TypeScript。它“解决”了 JS 的许多问题,是 JS 的一个“超集”,它将使代码易于阅读。有很多使用 TypeScript 的理由,但是我将给您 7 个不使用 TypeScript 的理由。

    TypeScript功能:const断言

    我发现官方的 TypeScript 文档非常有用,但是总觉得有点过于学术化并且枯燥无味。每当我发现一个新功能时,我想要知道这个功能究竟能够解决什么问题而不是长篇大论

    TypeScript基础以及在Vue中的应用

    TypeScript推出已经很长时间了,在Angular项目中开发比较普遍,随着Vue 3.0的即将推出,TypeScript在Vue项目中使用也即将成为很大的趋势,笔者也是最近才开始研究如何在Vue项目中使用TypeScript进行项目的开发。

    使用TypeScript两年后-值得吗?

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

    项目中使用 TypeScript 的一些感悟

    抛开以前做业务的时候的不完全使用,这次实践可以算是我第一次真正意义上的使用 ts。由于写法上的不同,以及对不熟悉事物的新鲜感,在这次项目开发的过程中着实有着许多感悟,于是打算写篇小东西好好记录下来

    5分钟了解TypeScript

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

    点击更多...

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