Implement Awaited Type Helper in TypeScript
Many asynchronous operations in JavaScript return Promises. When working with these Promises, you often need to extract the resolved value type of a Promise. This is crucial for type safety, especially when dealing with nested Promises or functions that return Promises. Your task is to implement a TypeScript utility type, similar to the built-in Awaited, that can recursively unwrap the type of a Promise.
Problem Description
You need to create a generic TypeScript type called MyAwaited<T>. This type should take a type T and return the type that T would resolve to if it were awaited.
Key Requirements:
- If
Tis a Promise,MyAwaited<T>should be the type of the value the Promise resolves to. - If
Tis not a Promise,MyAwaited<T>should simply beT. - The type should handle nested Promises (e.g.,
Promise<Promise<number>>). - The type should also handle "thenable" objects, which are objects that have a
thenmethod, as these can also be awaited in JavaScript.
Expected Behavior:
MyAwaited<Promise<number>>should benumber.MyAwaited<Promise<Promise<string>>>should bestring.MyAwaited<number>should benumber.MyAwaited<{ then: (onfulfilled: (value: string) => void) => void }>should bestring.
Examples
Example 1:
type Example1 = MyAwaited<Promise<number>>;
// Expected type: number
Explanation: Promise<number> is a Promise. Awaiting it resolves to number.
Example 2:
type Example2 = MyAwaited<Promise<Promise<string>>>;
// Expected type: string
Explanation: Promise<Promise<string>> is a Promise. Awaiting it resolves to Promise<string>. Awaiting that resolves to string.
Example 3:
type Example3 = MyAwaited<boolean>;
// Expected type: boolean
Explanation: boolean is not a Promise and does not have a then method. It is returned as is.
Example 4:
type Thenable = {
then: (onfulfilled: (value: { data: number }) => void) => void;
};
type Example4 = MyAwaited<Thenable>;
// Expected type: { data: number }
Explanation: Thenable is an object with a then method, making it "thenable". MyAwaited should unwrap the type resolved by its then method.
Constraints
- The solution must be a single generic type definition in TypeScript.
- No runtime JavaScript code is required; this is a purely static type-level problem.
- You cannot use the built-in
Awaitedutility type.
Notes
Consider how you can use conditional types (T extends U ? X : Y) and recursive type definitions to achieve this. Remember that Promise<T> and "thenable" objects are the primary targets for unwrapping. Think about the structure of a Promise and a thenable object.