所以我有这个帮助函数,它允许我根据结构匹配替换类型:
type Replace<T, C, A> = {
[P in keyof T]: T[P] extends C ? A : T[P]
}
这允许我执行以下操作:
type NumberThing = { value: number }
type StringThing = Replace<NumberThing, number, string>
const a: StringThing = { value: "cenas" }
一切都很好,花花公子,直到有人这样做:
type ArrayOfNumberThing = { value: Array<number> }
好的,所以,我只是添加一个新条件...
type Replace<T, C, A> = {
[P in keyof T]: T[P] extends C ? A : (T[P] extends Array<C> ? Array<A> : T[P])
}
它类型:
type ArrayOfNumberThing = { value: Array<number>, simpleValue: number }
type ArrayOfStringThing = Replace<ArrayOfNumberThing, number, string>
const b: ArrayOfStringThing = { value: ["cenas"], simpleValue: "still works" }
但这家伙很固执,现在扔给我一个:
type CrazyNumberThing = { value: Array<Array<Array<number>>> }
好吧,我总是可以这样做:
type RecursiveArrayReplace<T, C, A> = T extends C ? A : (T extends Array<infer E> ? RecursiveArrayReplace<E, C, A> : T)
...显然,它会深入搜索 Array 直到找到要替换的内容,对吗?正确的?错误的:
Type alias 'RecursiveArrayReplace' circularly references itself.
还没等我擦干眼泪,就有人扔给我一句:
type TupleStringNumberThing = { value: [string, number] }
...这让我蜷缩成胎儿的姿势,除非你们帮助我:(