我知道有一个几乎类似的问题,在打字脚本中,用尖括号“<>”括一个类意味着什么?
但是当我发现它在一个接口中以一种复杂的方式(对于新手来说)声明一个函数时,我仍然感到困惑。
getContent<K extends keyof ContentMap>(content: K, conf?: ContentMap[K]["conf"]): Promise<Readonly<ContentMap[K]["content"]>>;
尖括号被多次使用(甚至是递归使用)。我怎么看?
正如@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
当你学习打字时,你实际上学的不是一种语言,而是两种语言。第一种语言是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中,如果给出pair
number
(不是任何数字,“number”类型)和string
,您将返回[number,string]
,这是所有可能的number、string
数组的类型,如[1,“hi”]
或[3.14,“hey”]
。如果您给它string
和boolean
,您将得到所有数组的类型,如[“hi”,true]
、[“blah”,false]
。
与其他语言一样,Anders提供了基本的编程结构(概括一下,所有的编程结构都是类型,或者作用于类型,而不是值):
>
内置类型,如number
、string
、any
、{}
。这些类似于像“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
,这意味着a
是B
的子集,即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
,这是所有具有X
和Y
两个类型参数且返回值为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值的数组元