Finns det ett problem med TypeScripts typinferenz?


Titta på koden nedan

const foo = [1,2].map((item) => {

  const logic = item === 1 ? 'not' : 'and'; 
  
  return {
    logic,
  };
});

När muspekaren är över 'logic', är typen 'not'|'and' Men när muspekaren hovrar över 'foo' Men vid denna tidpunkt är typen av 'logic' sträng

Jag förväntar mig att denna 'logik' i foo också är av unionstyp

Svar #1

Detta beror på att elementtyperna i arrayen inte är nummerliteraler. De är bara siffror. Detsamma gäller för egenskaperna hos det returnerade objektet.

Du kan hantera detta på några olika sätt, det mest bekväma är att använda as const-typassertionen på själva arrayen. Kort sagt, denna assertion talar om för kompilatorn att behandla varje värde i arrayen som ett värde av const-typ och som du vet från att deklarera individuella variabler som const, resulterar detta i inferens av litterala typer.

För att lära dig mer om const-påståenden, se TypeScript-handboken

const foo = ([1,2] as const).map(item => {

  const logic = item === 1 ? 'not' : 'and'; 
  
  return {
    logic,
  } as const;
});

Observera hur vi också tillämpar denna typ av kirurg på återvärdet av map-callbacken. Påståendet gäller inte bara arrayelement utan även egenskapsvärdena hos objekt, vilket skapar literala typer av deras egenskaper

Du kan städa upp detta genom att extrahera en lokal

const values = [1,2] as const;

const foo = values.map(item => {

  const logic = item === 1 ? 'not' : 'and'; 
  
  return {
    logic,
  } as const;
});

Lekplatslänk

Svar #2

du kan skicka typen till map-callbacken som:

const foo = [1,2].map((item): {logic: 'not' | 'and' } => {

  const logic = item === 1 ? 'not' : 'and'; 
  
  return {
    logic,
  };
});