使用映射类型生成元组类型
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>;
早上好,
我正在努力实现以下目标,
创建一个将从以下对象获取键的类型
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>;