Microsoft/TypeScript

The order of values ​​in a union affects the correct type inference

Open

#59.729 aberto em 23 de ago. de 2024

Ver no GitHub
 (2 comments) (0 reactions) (0 assignees)TypeScript (6.726 forks)batch import
Domain: check: Type InferenceHelp WantedPossible ImprovementUnion Order Dependence

Métricas do repositório

Stars
 (48.455 stars)
Métricas de merge de PR
 (Mesclagem média 6d 17h) (9 fundiu PRs em 30d)

Description

🔎 Search Terms

union order type infer

🕗 Version & Regression Information

This is the behavior in every version I tried, and I reviewed the FAQ for entries about union / order

⏯ Playground Link

https://www.typescriptlang.org/play/?ts=5.5.4#code/C4TwDgpgBAshDO8CGBzaBeKBvKB7MwAlrgHbwD8AXFAEoQDGuATgCYA88wThJKANFACuJANYlcAdxIA+KAF8A3ACgloSFAASSEiwA2EJmwAqszAAoAtgmRpqRgJRR0sgG65CLZUpYNdSJtAAZsL0RKRQ8IIARvD03FEQxlAQAB7AEDrwsNaoENJmSlBFUGBIILq4SCyUhcVFAD7YUFaIuXbyUABkTQAW2noG1Fo6+oYm8rV1jTgtNhDUZo7OUEYd3Th9I4Oa-aPGsnK19tRuHl6RMXGECWZYtbNtUItOsrd4BMRk1DP+IhDA1AA5BZfv9AR05PY+LVNgMmAscPgwmR5EtZHc6pjigB6bFQAB65FqcmhkOUQA

💻 Code

type Message = { options?: Record<string, unknown> };

type Handler<T> = (message: T) => void;

declare function subscribe<T extends Message>(
    payload:
      | { message: T } & { handler: Handler<T> }
      | { message: () => T } & { handler: Handler<T> }
  ): void;

subscribe({
  message: () => ({ options: { market: 'market' } }),
  handler: ({ options }) => {
                  // ^? Record<string, unknown>
  },
});

🙁 Actual behavior

options type is Record<string, unknown>

🙂 Expected behavior

options type should be inferred as { market: string }

Additional information about the issue

if you reverse the order of values in the union:

declare function subscribe<T extends Message>(
    payload:
      | { message: () => T } & { handler: Handler<T> }
      | { message: T } & { handler: Handler<T> }
  ): void;

then the type will be inferred correctly

Guia do colaborador