You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Regression: Argument of type 'awaited T' is not assignable to parameter of type 'T' #37534
Expected behavior:
The above code should compile. The types area reasonable and it did compile in previous versions without awaited.
Actual behavior:
Type error on await executor():
Argument of type 'awaited T' is not assignable to parameter of type 'T'.
'T' could be instantiated with an arbitrary type which could be unrelated to 'awaited T'.ts(2345)
There are some workaround available (adding a constraint to T for example) but we're also considering adding a flag to allow the assignment to proceed even though it's unsound. Interested to hear your feedback and from others who encounter this error.
We don't want to add the flag unless we really need it. Assessing what kind of breaks people encounter in real codebases is how we're figuring that out.
Is there any real world example that this is unsound in?
Sure, any higher-order type operation involving Promise<T> is potentially a problem. Note that the actual type Promise<Promise<T>> never appears in this example:
// Previously-allowed but unsound definitionasyncfunctionmyAwaitWrong<T>(arg: Promise<T>): Promise<T[]>{// Proposed: That this be valid without a type assertionreturn[awaitarg]asany;}// Correct definition of an awaiting functionasyncfunctionmyAwaitRight<T>(arg: Promise<T>): Promise<(awaitedT)[]>{return[awaitarg];}// Toggle these to observe different behaviorconstmyAwait=myAwaitRight;// const myAwait = myAwaitWrong;classMyThing<T>{value!: T;// Returns Promise<T>asyncgetValue(){returnthis.value;}// Returns Promise<T[]>asyncdoSomething(){returnmyAwait(this.getValue());}}asyncfunctionf(){constp=newMyThing<Promise<string>>();// Under myAwaitWrong - m: Incorrectly Promise<string>[]// Under myAwaitRight - m: Correctly string[]constm=awaitp.doSomething();}
Because a Promise<Promise<string>> can't be constructed.
People keep saying this and I continually question what it means for this to be the case; it's like saying f(x) => abs(abs(x)) isn't a thing because abs is idempotent on itself. It's valid and you can do it. Higher-order constructions exist and you can't just say "abs(abs(x)) should be illegal" because it implies any higher-order type construction should be banned unless it somehow proves that it can never operate in a way that produces this result.
May I ask a question? Can I make the following type check?
async function* flatten<T>(generator: AsyncGenerator<T[]>): AsyncGenerator<T> {
for await (const array of generator) {
for (const value of array) {
yield (value as unknown) as T;
// ^^^^^^^^^^^^^^^^^^^^^^^
// Type 'awaited T' is not assignable to type 'T'.
// 'T' could be instantiated with an arbitrary type which could be unrelated to 'awaited T'.ts(2322)
}
}
}
Activity
RyanCavanaugh commentedon Mar 23, 2020
This is a correct error. You could have written code like this:
There are some workaround available (adding a constraint to
Tfor example) but we're also considering adding a flag to allow the assignment to proceed even though it's unsound. Interested to hear your feedback and from others who encounter this error.falsandtru commentedon Mar 23, 2020
strictAwaitedTypes was implemented but removed after in #35998. Ron Buckton (@rbuckton) Why?
RyanCavanaugh commentedon Mar 23, 2020
We don't want to add the flag unless we really need it. Assessing what kind of breaks people encounter in real codebases is how we're figuring that out.
Pajn commentedon Mar 23, 2020
Is there any real world example that this is unsound in? Because a
Promise<Promise<string>>string can't be constructed.Personally, I consider that Typescript allows
Promise<Promise<string>>to be written a bug (that hopefully can be fixed soon #29317)falsandtru commentedon Mar 23, 2020
#37501
Hm...
awaited operator is effective to find a bug but correcting for awaited operator was very bored.
falsandtru/spica@c569afd
#37511
RyanCavanaugh commentedon Mar 23, 2020
Sure, any higher-order type operation involving
Promise<T>is potentially a problem. Note that the actual typePromise<Promise<T>>never appears in this example:People keep saying this and I continually question what it means for this to be the case; it's like saying
f(x) => abs(abs(x))isn't a thing becauseabsis idempotent on itself. It's valid and you can do it. Higher-order constructions exist and you can't just say "abs(abs(x))should be illegal" because it implies any higher-order type construction should be banned unless it somehow proves that it can never operate in a way that produces this result.jeiea commentedon Mar 25, 2020
May I ask a question? Can I make the following type check?
I'm using typescript 3.9.0-dev.20200324.
falsandtru commentedon Mar 25, 2020
You have to change the return type to
AsyncGenerator<awaited T>.jeiea commentedon Mar 25, 2020
falsandtru (@falsandtru) It causes
Parsing error: '>' expected.