TypeScript: How to Properly Type a Function Returning a Promise of an Object with Conditional Properties?
I'm working on a TypeScript function that fetches user data based on a user ID. The API response structure varies depending on whether the user is an admin or a regular user. I want to type the return value of the function correctly to ensure I can handle both scenarios without losing type safety. My current implementation looks like this: ```typescript interface User { id: number; name: string; } interface Admin extends User { role: 'admin'; permissions: string[]; } interface RegularUser extends User { role: 'user'; subscribed: boolean; } type UserResponse = Admin | RegularUser; async function fetchUser(userId: number): Promise<UserResponse> { const response = await fetch(`https://api.example.com/users/${userId}`); const user: UserResponse = await response.json(); return user; } ``` However, when I try to use the function, I encounter an scenario with type narrowing. For example: ```typescript async function displayUserInfo(userId: number) { const user = await fetchUser(userId); console.log(user.name); if (user.role === 'admin') { console.log(user.permissions); // TypeScript behavior here } else { console.log(user.subscribed); // TypeScript behavior here } } ``` TypeScript gives me the following behavior messages: ``` Property 'permissions' does not exist on type 'UserResponse'. Property 'subscribed' does not exist on type 'UserResponse'. ``` I thought TypeScript would be able to narrow down the type based on the `role` property within the if-else blocks, but it seems like that isn't happening. I've also tried using type assertions, but that feels unsafe and defeats the purpose of type safety. What am I missing here? How can I properly type this function and ensure that TypeScript correctly narrows the types based on the role? I'm using TypeScript 4.5.2 and the strict flag is enabled in my tsconfig.json. Am I missing something obvious? What am I doing wrong?