Funktion för att omsluta ett värde till en array om det inte är det och ge rätt typ i TypeScript


Jag försöker skapa en funktion för att omsluta ett värde i en array om det inte är en array

export function asArray<T extends Array<any>>(value: T): T
export function asArray<T>(value: T): T[]
export function asArray(value: any) {
  return Array.isArray(value) ? value : [value]
}

Men det fungerar inte när värdetypen är en unionstyp

type A = { a: 1 } | { a: 1 }[]

const fn = (v: A) => {
  const b = asArray(v)
  return b[0].a
}

det kastar

Property 'a' does not exist on type 'A'.
  Property 'a' does not exist on type '{ a: 1; }[]'.ts(2339)

Svar #1

Din unionstyp är inte en array, så den använder den andra deklarationen:

function asArray<{ a: number } | { a: number }[]>(value: T): Array<{ a: number } | { a: number }[]>

Så för kompilatorn kan ditt b[0] antingen vara en { a: number } eller en array av det. Det kan därför inte vara säkert på att det finns en a-egenskap i det.

Du skulle bättre definiera din funktion som:

export function asArray<T>(value: T | T[]): T[] {
  return ([] as T[]).concat(value)
}

Detta skulle inte ens kräva en överbelastning.