尖括号“<>"是什么意思在 Typescript 中的函数声明中是什么意思? [英] What does angle brackets “<>” mean in function declaration in Typescript?

查看:32
本文介绍了尖括号“<>"是什么意思在 Typescript 中的函数声明中是什么意思?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道 在 TypeScript 中将类括在尖括号<>"中是什么意思?

但是当我发现它以一种复杂的(对于新手)方式用于在接口内声明函数时,它仍然让我感到困惑.

But it still confused me when I found it used in a complicated(for a newbie) way to declare a function inside a interface.

getContent<K extends keyof ContentMap>(content: K, conf?: ContentMap[K]["conf"]): Promise<Readonly<ContentMap[K]["content"]>>;

尖括号多次使用(甚至递归).我怎样才能阅读它?

The angle brackets used many times(even recursively). How can I read it?

推荐答案

当你学习 Typescript 时,你实际上学习的不是一种语言,而是两种.第一种语言是 Typescript 本身,它是带有类型注释和一些扩展的 Javascript,例如枚举"或公共/私有"类成员.第二种语言是类型语言.它没有正式名称,我们以发明者Anders Hejlsberg的名字命名它.

When you learn Typescript, you actually learn not one language, but two. The first language is the Typescript proper, which is Javascript with type annotations and some extensions, like "enum" or "public/private" class members. The second language is the language of types. It has no official name, let's call it Anders after the inventor, Anders Hejlsberg.

Anders 的目的是为您的程序生成动态类型.Typescript 处理字符串、数字、对象等值,而 Anders 只处理一种数据:类型本身.安德斯的价值观是类型.Anders 中的函数接受一个或多个类型参数并返回另一种类型.

The purpose of Anders is to generate dynamic types for your program. While Typescript manipulates values that are strings, numbers, objects etc, Anders only deals with a single kind of data: the type itself. Anders' values are types. A function in Anders accepts one or multiple type arguments and returns another type.

每次在程序中使用 <> 时,实际上是在编写 Anders 代码,而不是 Typescript 代码.可以显式调用此代码(当您编写类似 MyType<T> 之类的代码时),也可以通过类型推断在后台调用.

Every time you use <> in your program, you actually write Anders code, not Typescript code. This code can be called either explicitly (when you write something like MyType<T>), or under the hood, via type inference.

例如,这是一个 Typescript 函数,它接受两个值并根据它们返回另一个值:

For example, here's a Typescript function, which accepts two values and returns another value, based on them:

function pair (x, y) {
    return [x, y]
}

这是一个 Anders 函数,它接受两种类型并基于它们返回另一种类型:

This is an Anders function, which accepts two types and returns another type, based on them:

type Pair<U, V> = [U, V]

在 Typescript 中,如果你给 pair 两个值,你会得到这两个值的数组.

In Typescript, if you give pair two values, you'll get an array of these two values.

在 Anders 中,如果你给 Pair number(不是任何数字,数字"类型)和 string,你会取回 [number, string],它是所有可能的 number,string 数组的类型,例如 [1, "hi"][3.14, 嘿"].如果你给它 stringboolean,你会得到所有数组的类型,比如 ["hi", true], ["blah", false].

In Anders, if you give Pair number (not any number, the "number" type), and string, you'll get back [number, string], which is the type of all possible number,string arrays, like [1, "hi"] or [3.14, "hey"]. If you give it string and boolean, you'll get the type of all arrays like ["hi", true], ["blah", false].

与其他语言一样,Anders 提供了基本的编程结构(概括地说,所有这些都是类型或作用于类型,而不是值):

Like other languages, Anders provides basic programming constructs (that, to recap, all are types or act on types, not values):

  • 内置类型,例如 numberstringany{}.这些类似于 Typescript 内置对象,如Number"或String".

  • built-in types, like number, string, any, {}. These are similar to Typescript built-in objects like "Number" or "String".

文字,例如 "foo".这些类似于 Typescript 中的文字,但在 TS 中 "foo" 表示特定的字符串,例如字符序列 f, o, o,在 Anders 中表示一种类型,即所有为 foo 的字符串的类型",很明显,它只有一个可能的成员,"foo".

literals, like "foo". These are similar to literals in Typescript, but while in TS "foo" means a specific string, e.g. a sequence of characters f, o, o, in Anders it means a type, namely, "the type of all strings that are foo", which, obviously, has only one possible member, "foo".

联合,类似于 TS 中的数组:A|B|C.

unions, similar to arrays in TS: A|B|C.

结构,类似于TS中的对象.在 TS 中,对象将字符串映射到值.在 Anders 中,一个结构(又名映射类型")将类型映射到其他类型.索引运算符 S[B] 返回结构 S 映射到的类型 B

structures, similar to objects in TS. In TS, an object maps strings to values. In Anders, a structure (aka "mapped type"), maps types to other types. The index operator S[B] returns the type to which the structure S maps B

    {foo: string; bar:number}["foo"]` ====> string

  • 运算符,例如一元 keyof 运算符采用类型 A 并返回 A 的所有可能键的类型,即联合(数组)TypeOfKey1 |TypeOfKey2 |...

  • operators, e.g. the unary keyof operator takes a type A and returns the type of all possible keys of A, that is, a union (array) TypeOfKey1 | TypeOfKey2 | ...

        keyof {foo:string, bar:number} =====> "foo"|"bar"
    

  • 比较,比如 a >b 在 TS 中.Anders只有一种比较形式,A extends B,也就是说AB的子集,即所有可能的值类型 A 也是 B 的值,但不一定相反.

  • comparisons, like a > b in TS. Anders only has one form of comparison, A extends B, which means that A is a subset of B, that is, all possible values of the type A are also values of B, but not necessarily the other way around.

        "foo" extends string =====> ok
        "foo" extends "foo"|"bar" =====> ok
        "blag" extends "foo"|"bar" =====> not ok
    

  • 条件:<代码>比较?Type1 : Type2

    循环,如{[A in SomeUnion]: T}.这将创建一个结构,其键是联合成员,值是类型 T

    loops, like {[A in SomeUnion]: T}. This creates a structure, whose keys are the union members and values are of type T

        {[A in "foo"|"bar"]: number} =====> {foo:number, bar:number}
    

  • 函数调用,即SomeOtherTypeDeclaration

    最后,Anders 也有输入参数的类型检查,类似于 Typescript 中的 function foo(x:number).在 Anders 中,类型检查是一种比较,即 A extends B

    finally, Anders also have type checks for input parameters, similar to function foo(x:number) in Typescript. In Anders, a type check is a comparison, that is, A extends B

    现在,回到你的例子(为了清楚起见而简化).

    Now, back to your example (simplified for clarity).

    interface A {}
    interface B {}
    interface C {}
    interface D {}
    
    type ContentMap = {
      foo: {
          conf: A
          content: B
      },
      bar: {
          conf: C
          content: D
      }
    }
    
    function getContent<K extends keyof ContentMap>
      ( content: K,
        conf?: ContentMap[K]["conf"]
      ): Readonly<ContentMap[K]["content"]> {
          ...
      }
    

    getContent 是 Anders 函数,它接受一个类型 K 并返回另一个类型 (X, Y) =>Z,它是所有具有XY类型的两个参数并且返回值类型为Z的函数的类型>.

    getContent is the Anders function, which accepts a type K and returns another type (X, Y) => Z, which is a type of all functions that have two arguments of types X and Y and the return value is of type Z.

    让我们用不同的类型手动调用"这个函数,看看会发生什么.

    Let's "call" this function manually with different types and see what happens.

    1. getContent.首先,Anders 检查参数的类型.我们的类型检查是extends keyof ContentMap.我们还记得,keyof ContentMap 返回一个 ContentMap 的键数组,即 "foo"|"bar" 其中,>"foo""bar" 是类型,而不仅仅是字符串.然后,根据 "foo"|"bar" 检查我们的参数 number.很明显,number 不是这个类型的子集,所以类型检查失败,我们得到一个错误.

    1. getContent<number>. First off, Anders checks the type for the argument. Our type check is extends keyof ContentMap. As we recall, keyof ContentMap returns an array of keys of ContentMap, that is "foo"|"bar" where, again, "foo" and "bar" are types and not just strings. Then, our argument, number, is checked against "foo"|"bar". Obviously, number is not a subset of this type, so the type check fails and we get an error.

    getContent<"foo">.类型检查成功(因为"foo" "foo"|"bar" 的子集),我们可以继续.我们的任务是基于"foo"构造函数类型.第一个参数的类型为 K,与参数相同,所以它变成了 "foo".第二个参数两次应用索引运算符:首先,我们评估 ContentMap["foo"],它给我们 {conf: A, content: B} 然后我们应用["conf"],这给了我们A.以类似的方式,我们为返回类型获取B.最后,我们调用内置的Anders函数Readonly,返回另一种类型,我们称之为ReadonlyB,所以,我们得到的是函数类型(内容:foo",conf:A)=>ReadonlyB,这就是我们的 Anders 函数返回的内容.

    getContent<"foo">. The type check succeeds (since "foo" is a subset of "foo"|"bar") and we can proceed. Our task is to construct the function type based on "foo". The first param has the type K, the same as the argument, so it becomes just "foo". The second param applies the index operator twice: first, we evaluate ContentMap["foo"], which gives us {conf: A, content: B} and then we apply ["conf"], which gives us A. In the similar way, we obtain B for the return type. Finally, we call the built-in Anders function Readonly and get back another type, let's call it ReadonlyB, So, what we've got is the function type (content: "foo", conf: A) => ReadonlyB, and this is what our Anders function returns.

    getContent<"bar"> ...留作练习.

    现在,当你写这个的时候会发生什么?

    Now, what happens when you write this?

    let something = getContent('foo', {...})
    

    编译器看到您有一些与 getContent 相关的 Anders 代码并评估该代码,将 "foo" 作为参数传递.如上所示,返回类型将是 ("foo", A) =>只读B.然后,针对此类型检查上面的行,如果不匹配则失败,这基本上就是整个事情的全部内容.

    The compiler sees that you have some Anders code, related to getContent and evaluates that code, passing "foo" as an argument. As seen above, the return type will be ("foo", A) => ReadonlyB. Then, the above line is checked against this type, and fails if it doesn't match, which is basically what the whole thing is all about.

    希望这有帮助...

    这篇关于尖括号“&lt;&gt;"是什么意思在 Typescript 中的函数声明中是什么意思?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    相关文章
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆