我定义了一个架构
type Schema = {
a: { a: 1 }
b: { b: 2 }
}
Run Code Online (Sandbox Code Playgroud)
我想要一个函数来创建符合多个架构的对象。
function createObject<K extends keyof Schema>(schema: Array<K>, obj: Schema[K]) {}
createObject(["a"], { a: 1 }) // works
createObject(["b"], { b: 2 }) // works
createObject(["a", "b"], { b: 2 }) // doesn't error but it should
createObject(["a", "b"], { a: 1, b: 2 }) // works
Run Code Online (Sandbox Code Playgroud)
我已经尝试了其他一些东西。有趣的是,当您&与自己建立联合时,它会&在联合中的所有项目之间进行分配,而并不能完全满足我的需求。我希望有人{a: 1} | {b: 2}继续努力{a: 1, b: 2}。有任何想法吗?
假设Schema属性内的类型本身不是联合,则可以使用条件类型将联合类型转换为Schema[K]交集,如下所示:
type Schema = {
a: { a: 1 }
b: { b: 2 }
};
type UnionToIntersection<U> =
(U extends any ? (k: U) => void : never) extends
((k: infer I) => void) ? I : never
function createObject<K extends keyof Schema>(
schema: Array<K>,
obj: UnionToIntersection<Schema[K]>
) { }
createObject(["a"], { a: 1 }) // works
createObject(["b"], { b: 2 }) // works
createObject(["a", "b"], { b: 2 }) // error!
createObject(["a", "b"], { a: 1, b: 2 }) // works
Run Code Online (Sandbox Code Playgroud)
这对您来说可能就足够了。如果您还有其他用例(例如,如果Schema具有类似的属性,cd: {c: 3} | {d: 4}并且您希望最终类型中仍然存在联合),则更合适的解决方案是:
type PropsToIntersection<T, K extends keyof T> =
{ [P in K]: (k: T[P]) => void }[K] extends
((k: infer I) => void) ? I : never;
function createObject<K extends keyof Schema>(
schema: Array<K>,
obj: PropsToIntersection<Schema, K>
) { }
Run Code Online (Sandbox Code Playgroud)
相似之处在于它遍历的键,Schema然后执行交集,而不是传播的并集Schema[K]。同样,仅当某些架构属性本身可能是联合时,才会显示出差异。
好的,希望对您有所帮助。祝好运!
| 归档时间: |
|
| 查看次数: |
53 次 |
| 最近记录: |