当前位置: 首页 > 知识库问答 >
问题:

尖括号“”在TypeScript中的函数声明中意味着什么?

鲁鹤轩
2023-03-14

我知道有一个几乎类似的问题,在打字脚本中,用尖括号“<>”括一个类意味着什么?

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

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

尖括号被多次使用(甚至是递归使用)。我怎么看?

共有2个答案

冯通
2023-03-14

正如@axiac提到的,它与泛型有关。

你阅读它的方法是想着类型。

示例:

// generic class that deals with type T
class List<T> {}

// usage
const list1 = new List<string>() // list of type string
const list2 = new List<number>() // list of type number
const list3 = new List<any>()    // list of type any
吴高畅
2023-03-14

当你学习打字时,你实际上学的不是一种语言,而是两种语言。第一种语言是Typescript本身,它是带有类型注释和一些扩展(如“enum”或“public/private”类成员)的Javascript。第二种语言是类型语言。它没有正式的名字,让我们以发明者安德斯·海尔斯贝格的名字叫它安德斯吧。

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

每次在程序中使用<>时,实际上编写的是Anders代码,而不是Typescript代码。可以显式地调用此代码(当您编写类似myType 的代码时),也可以通过类型推断在引擎盖下调用此代码。

例如,这里有一个Typescript函数,它接受两个值并基于它们返回另一个值:

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

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

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

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

在Anders中,如果给出pairnumber(不是任何数字,“number”类型)和string,您将返回[number,string],这是所有可能的number、string数组的类型,如[1,“hi”][3.14,“hey”]。如果您给它stringboolean,您将得到所有数组的类型,如[“hi”,true][“blah”,false]

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

>

  • 内置类型,如numberstringany{}。这些类似于像“number”或“string”这样的Typescript内置对象。

    文字,如“foo”。这些类似于Typescript中的文字,但在TS中,“foo”表示一个特定的字符串,例如一系列字符F,o,o,而在Anders中,它表示一种类型,即“所有为foo的字符串的类型”,显然,它只有一个可能的成员“foo”

    联合,类似于ts:abc中的数组。

    结构,类似于ts中的对象。在TS中,对象将字符串映射到值。在Anders中,一种结构(也称为“映射类型”),将类型映射到其他类型。索引运算符s[B]返回结构s映射到的类型B

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

    运算符,例如一元keyof运算符采用类型a并返回a的所有可能键的类型,即union(数组)TypeOFKey1 TypeOfKey2...

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

    比较,如TS中的A>B。安德斯只有一种形式的比较,a扩展了B,这意味着aB的子集,即a类型的所有可能值也是B的值,但不一定相反。

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

    条件句:比较?Type1:Type2

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

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

    函数调用,它们是SomeOtherTypeDeclaration

    最后,Anders还对输入参数进行类型检查,类似于TypeScript中的函数foo(x:number)。在Anders中,类型检查是比较,即a扩展B

    现在,回到您的示例(为了清晰起见进行了简化)。

    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 。首先,Anders检查参数的类型。我们的类型检查是extends keyof contentmap。我们还记得,keyof contentMap返回contentMap的键数组,即“foo”“bar”,其中“foo”“bar”是类型,而不仅仅是字符串。然后,将我们的参数number“foo”“bar”进行检查。显然,number不是此类型的子集,因此类型检查失败,我们得到一个错误。

    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<“bar”>...作为练习保留。

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

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

    编译器看到您有一些与getcontent相关的Anders代码,并将“foo”作为参数传递给该代码。如上所述,返回类型将是(“foo”,A)=>readonlyb。然后,上面的行对照这个类型进行检查,如果不匹配就失败,这基本上是整个事情的全部。

    希望这有帮助...

  •  类似资料:
    • 问题内容: 我知道这要求声明的作用。 但是有时候我在要求之后看到了两个括号。 问) 这是什么意思,它是如何工作的? 问题答案: 这是一种将所需模块的设置为功能的模式。要求该模块返回一个函数,并在require之后的括号中使用参数对函数求值。 在上面的示例中,您的文件如下所示: 这种模式通常用于将变量传递给模块,就像上面用变量所见。

    • 问题内容: 下面是代码片段。 有人可以向我解释@符号在Java中的含义吗? 问题答案: 这是一个注释。 注释是元数据的一种形式。它们提供的程序数据不属于程序本身。注释对其注释的代码的操作没有直接影响。 注释确实会影响工具和库对待程序的方式,进而会影响正在运行的程序的语义。可以从源文件,类文件中读取注释,也可以在运行时从中读取注释。

    • 问题内容: 我正在使用Facebook库,其中包含以下代码: 函数定义开头的&是什么意思,以及如何使用这样的库(在一个简单的示例中) 问题答案: 函数名称前的与号表示函数将返回对变量的引用,而不是值。 当您想使用函数查找引用应绑定到哪个变量时,按引用返回很有用。不要使用引用返回来提高性能。引擎将自动自动优化它。仅在有充分的技术理由时才返回引用。

    • 问题内容: 使用或不使用变量访问变量之间有什么区别? 问题答案: 所述使它成为 用户定义 会话 变量。否则它将是 本地范围的 变量(在存储过程中),您必须先在本地使用它。如果需要,还可以设置 全局 系统 变量(使用或)。以及带有或或的会话 系统 变量。 有关详细信息,从文档:如果没有修饰符,改变会话变量(这就是为什么你在存储过程中的第一个当地人)。如果设置了多个系统变量,则该语句中的最新变量或修饰

    • 问题内容: $(‘button’).click(function () { 我的问题:尽管我打了个电话,为什么它仍然会提醒下一个号码?就像:忽略下面的代码,然后继续下一个元素 问题答案: 除了引发异常外,没有其他方法可以停止或中断循环。如果您需要这种行为,该方法是错误的工具。 提前终止可以通过以下方式完成: 一个简单的循环 一… 圈 另一个阵列的方法:,,,和测试使用谓词返回truthy值的数组元