Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

TypeScript arguments of union of functions are transformed to "never"

I have few different interfaces. Each of them contains property called type.

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

mapping interface

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

And union type

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

type TypeElement = Type1 | Type2 | Type3

Map object, that uses record of each type separately. Each record in the function has its own type. Just like the mapping interface

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

When I pass a variable of type TypeElement into a callback from allTypes, it gives me an error

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

Here cb type is ((record: Type1) => void) | ((record: Type2) => void) | ((record: Type3) => void)
But when I try to call it cb(record) it tells that cb type is (record: never) => void

The error is:

Argument of type ‘TypeElement’ is not assignable to parameter of type ‘never’.
The intersection ‘Type1 & Type2 & Type3’ was reduced to ‘never’ because property ‘type’ has conflicting types in some constituents.
Type ‘Type1’ is not assignable to type ‘never’.

Why I get that error? What is wrong with that? How I can pass record to cb without giving me an error? record as never, as any are not the solutions I am looking for!

>Solution :

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)
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading