使用映射类型生成元组类型

Generate Tuple Type using a mapped Type

早上好,

我正在努力实现以下目标,

创建一个将从以下对象获取键的类型

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

并使用映射类型生成元组类型,使

[ “setName”, “setAge” ]

我在这里可能完全错了,但对于映射类型,我认为这可行

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

但是如果 T 是我上面展示的对象的类型,我最终会得到以下类型

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

但我想要的是

type MappedType = [setName, setAge]

非常感谢任何帮助。

你真的需要元组类型还是数组类型可以?如果你只需要('setName', 'setAge')[],你可以轻松写(keyof typeof obj)[]。我认为没有必要将它变成元组类型 (it's definitely possible tho),因为我不会依赖对象属性的顺序,而元组通常会推断出其中事物的固定顺序。

你需要的是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