skip to Main Content

I would like to combine/reuse the type definitions for the following functions.

const zip = <T, K>(arr1: readonly T[], arr2: readonly K[]): Array<[T, K]> => arr1.map((k, i) => [k, arr2[i]])

const zipObj = <T extends string, K>(arr1: readonly T[], arr2: readonly K[]): { [key: string]: K} => 
  Object.fromEntries(zip(arr1, arr2))

// usage
const names = ['bob', 'sally', 'dave'] as const
const ages = [50, 40, 30] as const

const myEntries = zip(names, ages) // [['bob', 50], ['sally', 40], ['dave', 30]]
const myObj = zipObj(names, ages) // { 'bob': 50, 'sally': 40, 'dave': 30 }

How could I define type GeneralZipFunction in a way that re-uses T and K but allows me to A) override the return type and B) specify that T needs to extend string.

Ideally I could write:

const zip: GeneralZipFunction<some specifiers go in here> = // zip implementation
const zipObj: GeneralZipFunction<some specifiers go in here> // zipObj implementation

2

Answers


  1. You can try:

    type ZipObjectFunction = <T, K>(arr1: readonly T[], arr2: readonly K[]) => Object.fromEntries<Array<[T, K]>>
    

    Will this solve the problem?

    Login or Signup to reply.
  2. I’m pretty sure you can’t. TypeScript doesn’t allow abstracting over type parameters, you generally have to declare them explicitly. I don’t really see what advantage you’d gain by sharing types here.

    The closest things I could think of are

    • write a GeneralZipFunction type from which you can select the specific one:

      type GeneralZipFunction<X extends 'zip' | 'zipObj'> = {
        zip<T, K>(arr1: readonly T[], arr2: readonly K[]): Array<[T, K]>;
        zipObj<T extends string, K>(arr1: readonly T[], arr2: readonly K[]): Record<T, K>;
      }[X];
      const zip: GeneralZipFunction<'zip'> = …
      const zipObj: GeneralZipFunction<'zipObj'> = …
      
    • share only the parameter types:

      type GeneralZipArgs<T, K> = [arr1: readonly T[], arr2: readonly K[]]
      const zip: <T, K>(...args: GeneralZipArgs<T, K>) => Array<[T, K]> = …
      const zipObj: <T extends string, K>(...args: GeneralZipArgs<T, K>) => Record<T, K> = …
      
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search