TypeScript conditional types and how infer works