TypeScript-argument av union av funktioner omvandlas till "never"


Jag har några olika gränssnitt. Var och en av dem innehåller en egenskap som kallas type.

interface Type1 { type: 'key1', name: string }
interface Type2 { type: 'key2', description: string, name: string }
interface Type3 { type: 'key3', cost: number }

kartläggningsgränssnitt

interface TypeMap {
   key1: Type1,
   key2: Type2,
   key3: Type3
}

Och unionstyp

type TypeElement = Type1 | Type2 | Type3

Kartobjekt, som använder en post av varje typ separat. Varje post i funktionen har sin egen typ. Precis som mappningsgränssnittet

const allTypes: { [key in keyof TypeMap]: (record: TypeMap[key]) => void } = {
   key1: (record) => {},
   key2: (record) => {},
   key3: (record) => {},
}

När jag skickar en variabel av typen TypeElement till en callback från allTypes får jag ett fel

const func = (record: TypeElement) => {
   const cb = allTypes[record.type]
   return cb(record)
}

Här är cb-typen ((record: Type1) => void) | ((record: Type2) => void) | ((record: Type3) => void) Men när jag försöker anropa den cb(record) säger den att cb-typen är (record: never) => void

Felet är:

Argument av typen 'TypeElement' kan inte tilldelas parametern av typen 'never'. Snittet 'Type1 & Type2 & Type3' reducerades till 'never' eftersom egenskapen 'type' har motstridiga typer i vissa beståndsdelar. Typen 'Type1' kan inte tilldelas typen 'never'.

Varför får jag det felet? Vad är fel med det? Hur kan jag skicka posten till cb utan att få ett fel? record as never, as any är inte de lösningar jag letar efter!

Svar #1

interface Type1 { type: 'key1', name: string }
interface Type2 { type: 'key2', description: string, name: string }
interface Type3 { type: 'key3', cost: number }

interface TypeMap {
   key1: Type1,
   key2: Type2,
   key3: Type3
}

type TypeElement = Type1 | Type2 | Type3

const allTypes: { [key in keyof TypeMap]: (record: TypeMap[key]) => void } = {
   key1: (record) => {},
   key2: (record) => {},
   key3: (record) => {},
}

const func = <K extends keyof TypeMap>(record: TypeMap[K]) => {
   const cb = allTypes[record.type as K]
   return cb(record)
}