输入捕获的拒绝承诺 return 值
Typing a caught rejected promise return value
我希望这段代码能够编译:
function promiseCatchType(): Promise<[boolean, null]>
function promiseCatchType(): Promise<[null, string]> {
return new Promise((resolve, reject) => {
if (Math.random() > .5) {
return resolve();
} else {
return reject();
}
})
.then(() => [true, null])
.catch(() => [null, 'error']);
}
但它抛出我那个错误:
Type 'Promise<boolean[] | [any, string]>' is not assignable to type 'Promise<[null, string]>'.
Type 'boolean[] | [any, string]' is not assignable to type '[null, string]'.
Type 'boolean[]' is missing the following properties from type '[null, string]': 0, 1
在这里,我声明我的函数可以return两种不同类型的元组,一种在成功的情况下,另一种在不成功的情况下。
我想这样处理我的错误:
const [success, error] = await promiseCatchType();
if (error !== null) {
// error is a string
return 'An error occurred:' + error;
}
// Do something with `success`, if error is not null, then data must be of `boolean` type
有什么办法可以实现吗?
您必须进行两项更改,其中一项我理解,另一项我坦率地说不理解。 :-)
您需要声明两个外部签名,然后声明一个支持它们的实现签名。现在您只有一个外部签名和一个不兼容的实现签名。
你必须向 TypeScript 保证 [true, null]
是 [boolean, null]
。我不明白为什么。在将 [true, null]
推断为 (boolean|null)[]
而不是 [boolean, null]
,即使它推断 [null, 'error']
为 [null, string]
,而不是 (null|string)[]
。
所以:
function promiseCatchType(): Promise<[boolean, null]>; // 1
function promiseCatchType(): Promise<[null, string]>; // 1
function promiseCatchType(): Promise<[boolean, null]|[null, string]> { // 1
return new Promise((resolve, reject) => {
if (Math.random() > .5) {
return resolve();
} else {
return reject();
}
})
.then(() => [true, null] as [boolean, null])
// ^^^^^^^^^^^^^^^^^^^−−−−−−−−−−−−−−−−−−−−−−−−−− 2
.catch(() => [null, 'error']);
}
这里有几个问题:
您将 return 值表示为 overloads... 但是对于重载,实现的签名不算作调用签名之一。因此,您公开的唯一调用签名是 function promiseCatchType(): Promise<[boolean, null]>
。如果您想公开两个调用签名,您可以编写 function promiseCatchType(): Promise<[boolean, null]>; function promiseCatchType(): Promise<[null, string]>;
,然后编写一个 return 类似于 Promise<[null, string] | [boolean, null]>
的通用实现。但是:
仅 return 类型不同的重载通常没有用。编译器无法判断哪个调用签名 promiseCatchType()
应该匹配,实际上你在调用它时总是会得到第一个。相反,我会忘记重载并拥有一个 return 是 union.
的签名
像 [true, null]
这样的数组文字往往被推断为像 (boolean | null)[]
这样的数组,而不是元组。有不同的解决方法,但一种是明确断言 [true, null] as [boolean, null]
.
这使我得到以下代码:
function promiseCatchType(): Promise<[boolean, null] | [null, string]> {
return new Promise((resolve, reject) => {
if (Math.random() > .5) {
return resolve();
} else {
return reject();
}
})
.then(() => [true, null] as [boolean, null])
.catch(() => [null, 'error'] as [null, string]);
}
调用的时候又出现了一个问题。将数组解构为单独的 success
和 error
将使编译器无法跟踪它们之间的相关性。编译器通常无法将联合类型值视为相互关联。有关详细信息,请参阅 microsoft/TypeScript#30581。如果您检查 error === null
,编译器将无法理解这会使 success
成为 boolean
而不是 null
.
async function fooBad() {
const [success, error] = await promiseCatchType();
if (error !== null) {
return 'An error occurred:' + error;
} else {
success; // boolean | null ?!
}
return;
}
相反,您可以将未解构的元组视为 discriminated union,并且仅在测试后取出其成员。这行得通,但可能不像您想要的那样地道:
async function foo() {
const ret = await promiseCatchType();
if (ret[1] !== null) {
const error = ret[1];
return 'An error occurred:' + error;
} else {
const success = ret[0]; // boolean
}
return;
}
事实上,我倾向于从元组重构到更明显的可区分联合,如 {success: true, value: boolean} | {success: false, errorMessage: string}
,而不是完全不解构。但这开始离问题越来越远,所以我就到此为止。
希望对您有所帮助;祝你好运!
我希望这段代码能够编译:
function promiseCatchType(): Promise<[boolean, null]>
function promiseCatchType(): Promise<[null, string]> {
return new Promise((resolve, reject) => {
if (Math.random() > .5) {
return resolve();
} else {
return reject();
}
})
.then(() => [true, null])
.catch(() => [null, 'error']);
}
但它抛出我那个错误:
Type 'Promise<boolean[] | [any, string]>' is not assignable to type 'Promise<[null, string]>'.
Type 'boolean[] | [any, string]' is not assignable to type '[null, string]'.
Type 'boolean[]' is missing the following properties from type '[null, string]': 0, 1
在这里,我声明我的函数可以return两种不同类型的元组,一种在成功的情况下,另一种在不成功的情况下。
我想这样处理我的错误:
const [success, error] = await promiseCatchType();
if (error !== null) {
// error is a string
return 'An error occurred:' + error;
}
// Do something with `success`, if error is not null, then data must be of `boolean` type
有什么办法可以实现吗?
您必须进行两项更改,其中一项我理解,另一项我坦率地说不理解。 :-)
您需要声明两个外部签名,然后声明一个支持它们的实现签名。现在您只有一个外部签名和一个不兼容的实现签名。
你必须向 TypeScript 保证
[true, null]
是[boolean, null]
。我不明白为什么。在将[true, null]
推断为(boolean|null)[]
而不是[boolean, null]
,即使它推断[null, 'error']
为[null, string]
,而不是(null|string)[]
。
所以:
function promiseCatchType(): Promise<[boolean, null]>; // 1
function promiseCatchType(): Promise<[null, string]>; // 1
function promiseCatchType(): Promise<[boolean, null]|[null, string]> { // 1
return new Promise((resolve, reject) => {
if (Math.random() > .5) {
return resolve();
} else {
return reject();
}
})
.then(() => [true, null] as [boolean, null])
// ^^^^^^^^^^^^^^^^^^^−−−−−−−−−−−−−−−−−−−−−−−−−− 2
.catch(() => [null, 'error']);
}
这里有几个问题:
您将 return 值表示为 overloads... 但是对于重载,实现的签名不算作调用签名之一。因此,您公开的唯一调用签名是
function promiseCatchType(): Promise<[boolean, null]>
。如果您想公开两个调用签名,您可以编写function promiseCatchType(): Promise<[boolean, null]>; function promiseCatchType(): Promise<[null, string]>;
,然后编写一个 return 类似于Promise<[null, string] | [boolean, null]>
的通用实现。但是:仅 return 类型不同的重载通常没有用。编译器无法判断哪个调用签名
的签名promiseCatchType()
应该匹配,实际上你在调用它时总是会得到第一个。相反,我会忘记重载并拥有一个 return 是 union.像
[true, null]
这样的数组文字往往被推断为像(boolean | null)[]
这样的数组,而不是元组。有不同的解决方法,但一种是明确断言[true, null] as [boolean, null]
.
这使我得到以下代码:
function promiseCatchType(): Promise<[boolean, null] | [null, string]> {
return new Promise((resolve, reject) => {
if (Math.random() > .5) {
return resolve();
} else {
return reject();
}
})
.then(() => [true, null] as [boolean, null])
.catch(() => [null, 'error'] as [null, string]);
}
调用的时候又出现了一个问题。将数组解构为单独的 success
和 error
将使编译器无法跟踪它们之间的相关性。编译器通常无法将联合类型值视为相互关联。有关详细信息,请参阅 microsoft/TypeScript#30581。如果您检查 error === null
,编译器将无法理解这会使 success
成为 boolean
而不是 null
.
async function fooBad() {
const [success, error] = await promiseCatchType();
if (error !== null) {
return 'An error occurred:' + error;
} else {
success; // boolean | null ?!
}
return;
}
相反,您可以将未解构的元组视为 discriminated union,并且仅在测试后取出其成员。这行得通,但可能不像您想要的那样地道:
async function foo() {
const ret = await promiseCatchType();
if (ret[1] !== null) {
const error = ret[1];
return 'An error occurred:' + error;
} else {
const success = ret[0]; // boolean
}
return;
}
事实上,我倾向于从元组重构到更明显的可区分联合,如 {success: true, value: boolean} | {success: false, errorMessage: string}
,而不是完全不解构。但这开始离问题越来越远,所以我就到此为止。
希望对您有所帮助;祝你好运!