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

Jor*_*iro 1 types typescript mapped-types

早上好,

\n

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

\n

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

\n
const obj = {\n   setName: () => void;\n   setAge: () => void;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n
[ \xe2\x80\x9csetName\xe2\x80\x9d, \xe2\x80\x9csetAge\xe2\x80\x9d ]\n
Run Code Online (Sandbox Code Playgroud)\n

我在这里可能完全错误,但对于映射类型我认为这会起作用

\n
type MyType<T> = {\n  [P in keyof T]: T[P]\n}\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n
type MappedType = {\n    setName: () => void;\n    setAge: () => void;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

但我想要的是

\n
type MappedType = [setName, setAge]\n
Run Code Online (Sandbox Code Playgroud)\n

任何帮助是极大的赞赏。

\n

ecz*_*czn 5

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

Run Code Online (Sandbox Code Playgroud)

单击此处在 ts Playground 中尝试代码