I am confused. It well can be the result of ECMAScript spec or something, but all this doesn't make sense to me.
TypeScript Version: 3.7.x-dev.201xxxxx
Search Terms: promise undefined and I looked through all of the 5 pages + looked through FAQ
Code:
type TypeA = {
value: number;
}
const test = (): Promise<TypeA> => {
return new Promise<TypeA>(resolve => {
resolve(undefined); // Result of test() is Promise of TypeA. I return a promise that is resolved with undefined and it's ok for some reason.
});
};
const test2 = (): Promise<TypeA> => {
return Promise.resolve(undefined);
};
test().then(typeAInstance => {
// At this point here `typeAInstance` is of type TypeA and not! of `TypeA | undefined`
console.log(typeAInstance.value.toFixed())
});
Expected behavior:
Both Functions should prevent me from doing writing stupid code at compile time.
Actual behavior:
Only second one does prevent me. First one allows runtime error to happened in the end.
Playground Link: http://www.typescriptlang.org/play/?ts=3.8.0-dev.20200211&ssl=1&ssc=1&pln=14&pc=4#code/C4TwDgpgBAKuEEEoF4oG8BQUoDcCGANgK4QBcUAdkQLYBGEATgNwYC+GAxgPYUDOwUYBH4ooACgCU5AAoMu1AJa8IAHjiQEAPhTbM2BhGBEGFShADuUWfKWr1iTWIO8uBHNGS6s2KM9fuxIgoAEwgAMwUKCGCJFmxWWLYWbj4BIX4AJlFJGTlFZTV4LR10b31DY1NrfIgAOj83CECQ8MjoxNYWdOBJWuAACwgKMVANAElUvAoODy9sFJcCOoIuAHMRoon+KZna-GI64C4AMQUAD2jJCTZYoA
Related Issues:
I don't understand where this undefined as one of the potential argument types is coming from:

My lib.es5.d.ts contains this:
declare type PromiseConstructorLike = new <T>(executor: (resolve: (value?: T | PromiseLike<T>) => void, reject: (reason?: any) => void) => void) => PromiseLike<T>;
My lib.es2015.promise.d.ts contains this:
new <T>(executor: (resolve: (value?: T | PromiseLike<T>) => void, reject: (reason?: any) => void) => void): Promise<T>;
As @torifat pointed out, it does complain appropriately in Flow.
https://flow.org/try/#0PQKgBAAgZgNg9gdzCYAoVAXAngBwKZgAqueAgmALxgDeqYYAbgIYwCueAXGAHasC2AIzwAnANyoAvqgDGcbgGcMYDHkWUwACgCUXAArC4fAJby8AHmL5SAPkq3a9YXgyth3HniT7DJ85bLWGk7ycDAMBBT2dPRgwaHhGqzcACZ4UEbceMla4vQSOZLisgpKKooATOraegbGphYkNnY00Y7Oru7edXgAdHFheIkpaRlZBRLiZRjaPRgAFnjcGthWAJIlTNzSEVH0xSEwvfAA5suN64qb2z3MbL0YcABiRgAeWdpakjlAA
duplicate of #22040
I don't understand where this
undefinedas one of the potential argument types is coming from
It's an optional argument, and therefore accepts undefined.
@jcalz yeah, seems to be a duplicate. This is really a shame. I raised it because this caused an issue in production for me just now and I was really surprised TS can't handle such a simple case.
If resolve by default allows an optional argument, then all the .then callbacks should be also expected to be called with undefined regardless of the generic type defined.
This came up recently in our team chat and it was surprising to several of us. According to @rbuckton:
Because we (at the time) had no way to do
new Promise<void>(resolve => resolve()). Now we do (because void parameters are optional), so we can probably tighten up that definition.
So I鈥檓 going to leave this open so we can revisit it.
crosslinking to #27522
will this run afoul of #29131 ?
Hi, I'm running into a similar problem with type specificity for a generic callback type in our code on the mongodb node driver. The current callback definition looks something like:
type Callback<T = any> = (error?: Error, result?: T) => void;
Our desire is to explicitly disallow undefined for the result type, and I was hoping this would do the trick:
type Callback<T = any> = (error: Error | undefined | void, result: T | void) => void;
Alas it seems undefined equates to void in this case, so the elision of the void parameter isn't necessarily specific to the Promise case.
Most helpful comment
This came up recently in our team chat and it was surprising to several of us. According to @rbuckton:
So I鈥檓 going to leave this open so we can revisit it.