You can find the lib.es2015.promise.d.ts
source code at the end of this blog
.d.ts
文件
.d.ts
文件在 TypeScript 中被称为声明文件。这些文件的主要目的是为了提供 TypeScript 编译器关于 JavaScript 库的类型信息。JavaScript 是一种动态类型语言,因此它的库和框架通常不包含类型信息。为了在 TypeScript 中使用这些库和框架,开发者需 要提供类型信息,这就是 .d.ts
文件的作用。
在 .d.ts
文件中,你可以声明变量、函数、类等的类型,以便 TypeScript 编译器能理解这些 JavaScript 代码的类型信息。
举个例子,比如你在项目中使用了 jQuery 这个 JavaScript 库,但是 TypeScript 编译器并不知道 $
或 jQuery
这些对象的类型。在这种情况下,你需要一个 jquery.d.ts
文件,其中包含了所有 jQuery 对象和函数的类型声明,这样 TypeScript 编译器就能理解这些对象和函数了。
在大多数情况下,你不需要自己写 .d.ts
文件。许多流行的 JavaScript 库和框架的类型声明文件都可以在 DefinitelyTyped 项目中找到。你可以通过 npm 安装这些类型声明文件到你的项目中。
三斜线指令(Triple-Slash Directives)
///
是 TypeScript 中的一个特殊注释语法,称为三斜线指令(Triple-Slash Directives)。这种指令为编译器提供了某些指示或信息。
Triple-Slash Directives 是包含单个 XML 标签的单行注释。注释的内容会影响编译器的行为。比如:
/// <reference path="..." />
用来告诉编译器在编译当前文件时,还需要包含指定路径下的另一个文件。
/// <reference types="..." />
用来声明当前文件需要依赖的类型定义模块。
/// <reference lib="..." />
用来引入 额外的内置库文件(比如 "dom", "es2015" 等)。
/// <reference no-default-lib="true"/>
用来告诉编译器不要包含默认的库文件。
这些指令提供了一种在源文件中包含附加的编译信息的方式。
在这里的作用
interface PromiseConstructor {
readonly prototype: Promise<any>;
...
}
🤖:
这段代码看起来像是定义了一个 Promise 的 TypeScript 类型声明 (d.ts
) 文件。在这种情况下, /// <reference no-default-lib="true"/>
可能被使用的原因如下:
通常,TypeScript 在编译时会自动引入一些默认的库文件,包括对一些基本的 JavaScript 特性(如 Promise、Array、Object 等)的声明。这个行为通常是有用的,因为它让 TypeScript 能够理解并检查这些基本特性的使用。
然而,在这个特定的文件中,作者似乎想要自定义 Promise 的类型声明,可能是因为他们需要一些非标准的行为,或者他们正在创建一个特定的环境,这个环境需要特殊的 Promise 实现。
在这个情况下, /// <reference no-default-lib="true"/>
指令被添加到文件的开头,用来告诉 TypeScript 编译器在处理这个文件时,不要自动引入默认的库文件。这样,作者就可以自由地自定义 Promise 的类型声明,而不用担心和默认的声明冲突。
declare
这是 TypeScript 代码,declare var Promise: PromiseConstructor;
这一句的意思是声明一个全局的变量 Promise
,它的类型是 PromiseConstructor
。
在 TypeScript 中,declare var
用于声明全局变量。Promise
是 JavaScript 的一个内置对象,用于处理异步操作。在这里,这句代码是在告诉 TypeScript,全局有一个名为 Promise 的变量,并且它的类型是 PromiseConstructor
。
PromiseConstructor
是一个接口,定义了 Promise 对象的构造函数和一些静态方法,例如 all
, race
, reject
和 resolve
。
当你在代码中使用 Promise
对象时,TypeScript 就会根据这个声明来检查你的代码是否正确使用了 Promise
和它的方法。
==到这里就可以理解到: 在ts中使用 Promise 类型时,他类型信息就在这个文件声明定义了==
prototype TODO
interface PromiseConstructor {
readonly prototype: Promise<any>; 这个咋理解
...
}
all 方法
all<T extends readonly unknown[] | []>(values: T): Promise<{ -readonly [P in keyof T]: Awaited<T[P]> }>;
🤖:
这是 TypeScript 中的一个泛型方法声明,我们逐部分来看:
-
all<T extends readonly unknown[] | []>
: 这是声明一个泛型方法 all
,T
是泛型参数。T extends readonly unknown[] | []
指定了 T
可以是任何只读数组,或者空数组。unknown
是 TypeScript 的一个类型,表示未知类型。这里的 unknown[]
表示元素类型未知的数组。
-
(values: T)
: 这是方法的参数列表。方法接收一个名为 values
的参数,其类型为 T
。因为 T
已经被定义为只读数组或空数组,所以 values
必须是这些类型的实例。
-
Promise<{ -readonly [P in keyof T]: Awaited<T[P]> }>
: 这是方法的返回类型。这个方法返回一个 Promise
对象,这个 Promise
对象解析后的结果是一个对象。这个对象的类型通过映射类型 { -readonly [P in keyof T]: Awaited<T[P]> }
定义。
-
{ -readonly [P in keyof T]: Awaited<T[P]> }
是一个映射类型,它会遍历 T
(即 values
参数的类型)的所有键(即数组的索引),并将每个键 P
映射为一个新的类型 Awaited<T[P]>
。
-
Awaited<T[P]>
是一个条件类型,它等待 T[P]
的 Promise 解析。如果 T[P]
是一个 Promise,Awaited<T[P]>
就是这个 Promise 解析后的类型;如果 T[P]
不是一个 Promise,Awaited<T[P]>
就是 T[P]
。
-
-readonly
用于移除映射类型的 readonly
修饰符,使得结果类型的属性不是只读的。
总的来说,这个方法接收一个只读数组(或空数组),数组中的元素可以是 Promise 或者非 Promise。这个方法返回一个 Promise,这个 Promise 解析后的结果是一个对象,这个对象的每个属性都对应输入数组的一个元素,属性的类型是相应元素的 Promise 解析后的类型(如果元素是 Promise 的话)。
why there's a -
before readonly
🤖:
In TypeScript, the -
prefix before a modifier like readonly
in a mapped type is used to remove that modifier.
In the context of this specific type { -readonly [P in keyof T]: Awaited<T[P]> }
, the -readonly
is used to ensure that the resulting mapped type's properties are not readonly
, even if they were readonly
in the original type T
.
This syntax is useful when you want to create a new type based on an existing type, but you want to change some modifiers of the original type. For instance, if you want to create a new type that is similar to an existing type but allows mutation of the properties, you can use -readonly
to remove the readonly
modifier from the properties.
Here's a simple example:
type ReadonlyType = {
readonly a: number;
readonly b: number;
};
type MutableType = {
-readonly [P in keyof ReadonlyType]: ReadonlyType[P];
};
In MutableType
, the -readonly
removes the readonly
modifier from the properties of ReadonlyType
, creating a new type where a
and b
can be mutated.
Example
🤖:
这个描述是JavaScript中 Promise.all
方法的用法,下面是一个例子:
function asyncOperation(value, delay) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (delay > 2000) {
reject('Delay is too long');
} else {
resolve(value);
}
}, delay);
});
}
let promises = [asyncOperation('first', 1000), asyncOperation('second', 500), asyncOperation('third', 1500)];
Promise.all(promises)
.then(results => {
console.log(results);
})
.catch(error => {
console.log('Error: ' + error);
});
在这个例子中,Promise.all
接收一个Promise数组作为参数,返回一个新的Promise。当所有Promise都解决时,返回的Promise会解决,并且解决值是一个包含所有解决值的数组。如果有任何一个Promise被拒绝,返回的Promise就会被拒绝,拒绝理由是第一个被拒绝的Promise的拒绝理由。
Await type
type Awaited<T> =
T extends null | undefined ? T :
T extends object & { then(onfulfilled: infer F, ...args: infer _): any } ?
F extends ((value: infer V, ...args: infer _) => any) ?
Awaited<V> :
never :
T;
怎么读: 三元表达式,找问号和冒号
这是一个 TypeScript 中的高级类型(Advanced Type)定义,其名为 Awaited
。这个类型是用来递归地解开一个类型的 "awaited type"。换句话说,它是用来获取到一个 Promise 所包裹的类型。
让我们一步步地理解这个定义:
-
T extends null | undefined ? T :
:如果 T 是 null 或 undefined,直接返回 T。这是针对 TypeScript 非严格空值检查模式下的特殊情况。
-
T extends object & { then(onfulfilled: infer F, ...args: infer _): any } ?
:这个判断是查看 T 是否是一个包含 then
方法的对象。如果 T 是一个对象,并且这个对象有一个 then
方法,那么就进入下一步的判断。如果不是,就直接返回 T。
-
F extends ((value: infer V, ...args: infer _) => any) ?
:这个判断是查看 then
方法的第一个参数是否是一个函数。如果是,那么就提取出这个函数的第一个参数的类型(V),并进入下一步的判断。
-
Awaited<V> :
:如果上一步的判断成立,那么就递归地对 V 使用 Awaited
类型,也就是尝试继续解开 V 的 "awaited type"。如果 V 不是一个 Promise,那么这个递归就会在第二步的 T extends object & { then(onfulfilled: infer F, ...args: infer _): any } ?
那里结束,并返回 V。
-
never :
:如果 then
方法的第一个参数不是一个函数,那么就返回 never。
综上,这个 Awaited
类型实际上是用来解开一个 Promise 类型,获取到 Promise 所包裹的类型。例如,如果有 type X = Promise<string>
,那么 Awaited<X>
就会是 string
。如果 X
是一个 Promise<Promise<string>>
,那么 Awaited<X>
也会是 string
,因为 Awaited
会递归地解开所有层级的 Promise。
Source Code
lib.es2015.promise.d.ts source code
interface PromiseConstructor {
readonly prototype: Promise<any>;
new <T>(executor: (resolve: (value: T | PromiseLike<T>) => void, reject: (reason?: any) => void) => void): Promise<T>;
all<T extends readonly unknown[] | []>(values: T): Promise<{ -readonly [P in keyof T]: Awaited<T[P]> }>;
race<T extends readonly unknown[] | []>(values: T): Promise<Awaited<T[number]>>;
reject<T = never>(reason?: any): Promise<T>;
resolve(): Promise<void>;
resolve<T>(value: T): Promise<Awaited<T>>;
resolve<T>(value: T | PromiseLike<T>): Promise<Awaited<T>>;
}
declare var Promise: PromiseConstructor;