Home > Enterprise >  Generate Tuple Type using a mapped Type
Generate Tuple Type using a mapped Type

Time:05-10

Good morning,

I'm trying to achieve the following,

Create a type that will take the keys from the following object

const obj = {
   setName: () => void;
   setAge: () => void;
}

And generate a Tuple type using a mapped type that makes

[ “setName”, “setAge” ]

I might be completely wrong here but for the mapped type I think this would work

type MyType<T> = {
  [P in keyof T]: T[P]
}

But if T is a type from the object I showcased above, I would end up with the following type

type MappedType = {
    setName: () => void;
    setAge: () => void;
}

But what I want is

type MappedType = [setName, setAge]

Any help is greatly appreciated.

CodePudding user response:

what you need is UnionToTuple<U>:

// T ====> [...T, E]
type Push<T, E> = T extends any[] ? [...T, E] : [];


// union to intersection of functions
// UnionToIoFn<'a' | 'b'>
// ====> ((x: 'a') => void) & ((x: 'b') => void)
// ====> that equal to { (x: 'a'): void; (x: 'b'): void }
type UnionToIoFn<U> =
    (U extends any ? (k: (x: U) => void) => void : never) extends
    ((k: infer I) => void) ? I : never



// UnionPop<((x: 'a') => void) & ((x: 'b') => void)> ===> 'b'
// UnionPop<{ (x: 'a'): void; (x: 'b'): void }> ===> 'b'
type UnionPop<F> =
    F extends ({ (x: infer X): void; })
        ? X
        : never;


type UnionToTupleIter<U, Res> =
    [U] extends [never]
        ? Res
        : UnionToTupleIter<
            Exclude<U, UnionPop<UnionToIoFn<U>>> ,
            Push<Res, UnionPop<UnionToIoFn<U>>>
          >


type UnionToTuple<U> = UnionToTupleIter<U, []>;




// test
const obj = {
   setName: () => {},
   setAge: () => {},
}
// You wanted
// type YouWanted = ["setAge", "setName"]
type YouWanted = UnionToTuple<keyof typeof obj>;

click here to try the code in ts playground

CodePudding user response:

Do you really need a Tuple type or is an Array type ok? If you just need ('setName', 'setAge')[], you can easily write (keyof typeof obj)[]. I don't think it's necessary to make it into an tuple type (it's definitely possible tho), since I wouldn't rely on the order of object properties, and tuples typically infer a fixed ordering of things in it.

  • Related