Awaitable Helper Function in TypeScript
Asynchronous operations are fundamental in modern JavaScript and TypeScript development. Creating a reusable helper function that simplifies awaiting promises, especially when dealing with potentially non-promise values, can significantly improve code readability and reduce boilerplate. This challenge asks you to implement such a helper function.
Problem Description
You are tasked with creating a TypeScript function called awaitable that takes a value as input and returns a promise that resolves to that value if it's not already a promise. If the input is a promise, the function should simply return the promise itself. This allows you to consistently await the result of a function call, regardless of whether it returns a promise or a regular value.
Key Requirements:
- The function must be type-safe in TypeScript. It should correctly infer the type of the awaited value.
- The function should handle both promise and non-promise values gracefully.
- The function should not modify the original input value.
- The function should return a promise that resolves to the original value.
Expected Behavior:
- If the input is a promise,
awaitable(promise)should return the same promise. - If the input is not a promise,
awaitable(value)should return a new promise that resolves tovalue.
Edge Cases to Consider:
- Null or undefined input.
- Values that behave like promises but are not instances of
Promise. (While not strictly required to handle these, consider how your solution might behave). - Input that throws an error. The
awaitablefunction should not mask errors thrown by the input value.
Examples
Example 1:
Input: awaitable(42)
Output: Promise<42>
Explanation: The input is a number (not a promise). The function returns a promise that resolves to 42.
Example 2:
Input: awaitable(Promise.resolve("hello"))
Output: Promise<string>
Explanation: The input is a promise. The function returns the same promise.
Example 3:
Input: awaitable(() => 10) // A function that returns a number
Output: Promise<10>
Explanation: The input is a function. The function returns a promise that resolves to the result of the function call.
Example 4:
Input: awaitable(null)
Output: Promise<null>
Explanation: The input is null. The function returns a promise that resolves to null.
Constraints
- The function must be written in TypeScript.
- The function should be as concise and efficient as possible.
- The function should not rely on external libraries.
- The function should handle any valid TypeScript type as input.
Notes
Consider using the typeof operator and the Promise constructor to determine if a value is a promise. Think about how to correctly infer the type of the awaited value to maintain type safety. The goal is to create a utility function that simplifies asynchronous code and improves readability. Don't try to handle every possible "promise-like" object; focus on standard Promise instances and non-promise values.