问题
How do I set the type of the rejection of my promise? Let's say I do:
const start = (): Promise<string> => {
return new Promise((resolve, reject) => {
if (someCondition) {
resolve('correct!');
} else {
reject(-1);
}
});
}
Let's say I want to reject with a number. But I cannot set the type; I can pass whatever I want to the reject
here.
Moreover, when using this promise, I want to have compiling error if I use the rejection response type incorrectly.
回答1:
As explained in this issue, Promise
doesn't have different types for fulfilled and rejected promises. reject
accepts any argument that doesn't affect type of a promise.
Currently Promise
cannot be typed any better. This results from the fact that a promise can be rejected by throw
ing inside then
or catch
(this is a preferable way to reject existing promise), and this cannot be handled by typing system; also, TypeScript also doesn't have exception-specific types except never.
回答2:
The exception is typed any because we cannot guarantee the correct type of the exception at design time, and neither TypeScript nor JavaScript provide the ability to guard exception types at run time. Your best option is to use type guards to provide both a design-time and run-time check in your code.
source
回答3:
Cause there is no way to set error type in some cases like Promise, or exception throws, we can work with errors in rust-like style:
// Result<T, E> is the type used for returning and propagating errors.
// It is an sum type with the variants,
// Ok<T>, representing success and containing a value, and
// Err<E>, representing error and containing an error value.
export type Ok<T> = { _tag: "Ok"; ok: T };
export type Err<E> = { _tag: "Err"; err: E };
export type Result<T, E> = Ok<T> | Err<E>;
export const Result = Object.freeze({
Ok: <T, E>(ok: T): Result<T, E> => ({ _tag: "Ok", ok }),
Err: <T, E>(err: E): Result<T, E> => ({ _tag: "Err", err }),
});
const start = (): Promise<Result<string, number>> => {
return new Promise((resolve) => {
resolve(someCondition ? Result.Ok("correct!") : Result.Err(-1));
});
};
start().then((r) => {
switch (r._tag) {
case "Ok": {
console.log(`Ok { ${r.ok} }`);
break;
}
case "Err": {
console.log(`Err { ${r.err} }`);
break;
}
}
});
回答4:
What @EstusFlask mentioned in his answer is correct.
But I want go one step near to an artificial solution to simulate what we want with
TypeScript
capabilities.
Sometimes I use this pattern in my codes😉:
interface IMyEx{
errorId:number;
}
class MyEx implements IMyEx{
errorId:number;
constructor(errorId:number) {
this.errorId = errorId;
}
}
// -------------------------------------------------------
var prom = new Promise(function(resolve, reject) {
try {
if(..........)
resolve('Huuuraaa');
else
reject(new MyEx(100));
}
catch (error) {
reject(new MyEx(101));
}
});
// -------------------------------------------------------
prom()
.then(success => {
try {
}
catch (error) {
throw new MyEx(102);
}
})
.catch(reason=>{
const myEx = reason as IMyEx;
if (myEx && myEx.errorId) {
console.log('known error', myEx)
}else{
console.log('unknown error', reason)
}
})
回答5:
You can now use PromiseRejectionEvent
to type this (in everything except IE, of course):
MDN Documentation
Microsoft Documentation
来源:https://stackoverflow.com/questions/50071115/typescript-promise-rejection-type