zedryas
zedryas

Reputation: 974

Typescript: can't define return type of a function from multiple conditional typings

I'm tring to build a return type of a function from multiple conditional typings. What i'am trying to get as the returns of the function buildKindsFor is an object containing all kinds possible keys variation attached to a function.

Code sample will be better, in the first one everything is ok:

type KindNames =
  | 'one' | 'two' | 'three'

type KindShort<T extends  KindNames> =
  T extends 'one' ? 'o' : T extends 'two' ? 'tw' : 'th'

type KindPluralized<T extends  KindNames> =
  T extends 'one' ? 'ones' : T extends 'two' ? 'twos' : 'threes'

const buildKindsFor = <
  K extends KindNames,
  S extends KindShort<K>,
  P extends KindPluralized<K>,
>(
  kind: K,
  fn: (kind: KindNames, obj: any) => any,
): {
  [A in K]: () => any
} => {
  throw new Error ('Yet to implement !')
}

But when I try to add an entry in the returns object, let's say the short version, everything breaks such as (the error is all over, in comments are some of the messages when i hover over in the IDE):

const buildKindsFor = <
  K extends KindNames,
  S extends KindShort<K>, // Cannot find name K
  P extends KindPluralized<K>, // 'KindPluralized' only refers to a type, but is being used as a value here
>(
  kind: K,
  fn: (kind: KindNames, obj: any) => any,
): {
  [A in K]: () => any // ';' expected, ... and so on
  [B in S]: () => boolean
} => {
  throw new Error ('Yet to implement !')
}

The expected returns type for a call to let's say buildKindsFor ('one', dummyFn) should be something like:

{
  one: () => any
  o: () => boolean
  ones: () => string
}

Thanks in advance for anyone who could point me what i am missing. Seb

Upvotes: 1

Views: 65

Answers (1)

jcalz
jcalz

Reputation: 328433

This is a syntax error in your mapped type causing the parser to become unhappy all over the place. You can't make a mapped type with two indexes.

{ [A in K]: () => any, [B in S]: () => boolean } // syntax error!

Either use an intersection

{ [A in K]: () => any } & { [B in S]: () => boolean }

or make the indexer a union of the keys you care about:

{ [A in K | S]: A extends K ? (() => any) : (() => boolean) }

Either way should clear up those errors.


As an aside, the second and third type parameters S and P are not really needed, unless I'm missing something. You can just replace S with KindShort<K> and P with KindPluralized<K> and it should work for you.


Hope that helps; good luck!

Upvotes: 3

Related Questions