microsoft / microsoft/TypeScript

`silentNeverType` leak through return type inference

Aperta
#62,824 2 commenti 0 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

Bug Domain: check: Type Inference Help Wanted
Lingua principale
Go
Stelle
111k
Fork
14.3k
Merge medio
2g 4h
PR unite (30g)
132

Descrizione

🔎 Search Terms

silent never leak reverse mapped types nested calls return type inference

🕗 Version & Regression Information
  • This is the behavior in every version I tried
⏯ Playground Link

https://www.typescriptlang.org/play/?noEmit=true&ts=6.0.0-dev.20251202#code/C4TwDgpgBAaghgGwK4QM4B4AqA+KBeKTAbQGsIQB7AM0IF0BuAKEdEigFk4BjACwEsAdhADCFAcAgAPYPigAlCFwoAnACbpUwZYIDmAGihwBIbE0aCJyqt2gAFOMrgBbCJb4AvCKoDyAIwBWijIA3oxQUKwQAFxQmtoCOkzhYA7OqAD8MUgCJAIUAO4CTAC+zJFQAIJcwHxiAGLZ1bUC6GGEouJSMl0QAqqoHNz8Qh0S0nptmPaOTgM9fQPTzq4Q2p4+AUFEAEQpM6jbtFAAPlDZqhBUgl4T4ZhVNWJQ8-1QSy5u636B1RO4BKFwgAKaqSGKYUZdAx7NLg96oACUMQAbhQ+KoklAAPoUJDALH3JpiTKEB7NEpmcqYCjvFZrLzfIKtO60z5eThgZ7SXqvBRKNTM8KxLS6W5C1mrDwMzbVHYw2aHE5nPqXa6qNrYP6yeDINDoQFQIgAaSggigZEoNCmqQ+kvWHKgADJhfEdLQYgbwpEYkbMckbag4Ta6VLVBzjQw2sUSqYyuBoKIEAggmSxBhJpDpFyJAtBrxrpngGLrftszzFsG2RsfsA5QHFadzqqhKotQQgW1PVAlJ1xm1wr0AI4oFBi4oe-vdsRjYDgwt+54CYcQFAxIHcR4CNcI-C4VHond4PdojFRsXywOEeETQ-H9FmC5cBAOaBURqbxfLlCpgTpu6Fstc04fMRmnKFJnhQDXglelqy2XZ6yORsVSuFtix-KCKxmEMvhlGQCBg0NGV+RhsA7cIlCTIIYkTZNqh-DAITA8YrwDTVGCRSoiQEBoBG4rBCwMEs0iEn9Y0YR9n2UV932aWJXCQMBBSY3tum5IChgLZii0mBjMPkRQVHUSc4lFSdCNwms632BtlQuVCvA1WRgmKP4gQNSJUDFDdmi8xhxygDz4wyD0p1UkkVJnKBozaHy0xJLtjVNARzXIahSW41B3S4zdeP4yd-20sUhQyzdUAjYqhWpCzpRrLAGOwSdY3CGLik4-dT0YVAFLAdzYsyicStUCgAGVgCQKgqBiIcRwgBigSBLFoQDGIBCQJxfFWW9ArascJjasxuvG3qDTi39BqFYaxomqbP1m+bFuW-ZVvWzblG2lyEUq4bvGAHhVmuya1yWqALxiUyEg+1yz38hFDp6vrwjOy8uyu8agbulc5syhaQbBqA1o2rbdx2r7Jx+v6AfR27FpiIwQCe2EXV0KG9thpggA

💻 Code
type Values<T> = T[keyof T];

type MachineContext = Record<string, any>;

interface ParameterizedObject {
  type: string;
  params?: unknown;
}

type ActionFunction<
  TContext extends MachineContext,
  TParams extends ParameterizedObject["params"] | undefined,
  TAction extends ParameterizedObject,
> = {
  (ctx: TContext, params: TParams): void;
  _out_TAction?: TAction;
};

type ToParameterizedObject<
  TParameterizedMap extends Record<
    string,
    ParameterizedObject["params"] | undefined
  >,
> = Values<{
  [K in keyof TParameterizedMap & string]: {
    type: K;
    params: TParameterizedMap[K];
  };
}>;

type CollectActions<
  TContext extends MachineContext,
  TParams extends ParameterizedObject["params"] | undefined,
> = (
  {
    context,
    enqueue,
  }: {
    context: TContext;
    enqueue: (action: () => void) => void;
  },
  params: TParams,
) => void;

declare function enqueueActions<
  TContext extends MachineContext,
  TParams extends ParameterizedObject["params"] | undefined,
  TAction extends ParameterizedObject = ParameterizedObject,
>(
  collect: CollectActions<TContext, TParams>,
): ActionFunction<TContext, TParams, TAction>;

declare function setup<
  TContext extends MachineContext,
  TActions extends Record<
    string,
    ParameterizedObject["params"] | undefined
  > = {},
>({
  types,
  actions,
}: {
  types?: { context?: TContext };
  actions?: {
    [K in keyof TActions]: ActionFunction<
      TContext,
      TActions[K],
      ToParameterizedObject<TActions>
    >;
  };
}): void;

setup({
  actions: {
    doStuff: enqueueActions((_, params: number) => {}),
  },
});

setup({
  actions: {
    doStuff: enqueueActions((_, params: number) => {}),
    doOtherStuff: (_, params: string) => {},
  },
});

setup({
  actions: {
    doStuff: enqueueActions((_, params: number) => {}),
    doOtherStuff: (_: any, params: string) => {},
  },
});
🙁 Actual behavior

First 2 calls mention such a relationship check failure in the error message:

Type 'ActionFunction<MachineContext, number, { type: string; params: never; }>' is not assignable to type 'ActionFunction<MachineContext, number, { type: "doStuff"; params: number; }>'.

Notice never there. This is quite weird an unexpected as there is no never in sight here. It turns out this is a silentNeverType that leaked through.

🙂 Expected behavior

At the very least, I would expect it to error with consistent error messages mentioning unknown instead of never. Even better, if it could behave closer to a very similar version of this code: TS playground. In there the third error still errors but the first two infers nicely.

Additional information about the issue

No response

Guida per i contributori

Apri la guida per i contributori

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Direzione di ricerca

Inizia riproducendo l’esempio Playground collegato e confronta le diagnosi per le tre chiamate di configurazione, in particolare il silentNeverType trapelato nelle prime due. Traccia i percorsi coinvolti di inferenza dei tipi e verifica delle relazioni di TypeScript; il lavoro è completato quando le prime due chiamate inferiscono come previsto oppure segnalano errori coerenti basati su unknown senza esporre never.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Stack tecnologico
typescript
Ambito
compilers
Tipo di issue
Bug
Difficoltà
4/5
Tempo stimato
3-5 giorni
Stato di attività
Ferma
Chiarezza
Abbastanza chiara
Idoneità per principianti
35/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.