有可能吗?对你应该这样做吗?可能不是...
以下解决方案将生成对给定Payload
类型有效的字符串文字类型的所有可能组合.
type Expand<T> = T extends infer U ? { [K in keyof U]: U[K] } : never
type OptionalProps<T extends object> = Exclude<{
[K in keyof T]: T extends Record<K, T[K]>
? never
: K
}[keyof T], undefined>
type AllPermutations<T extends string, O extends string> = [T] extends [keyof T] ? [] : {
[K in T]:
K extends O
? [
...(AllPermutations<Exclude<T, K>, O> extends infer U extends string[]
? U
: never)
]
| [
K, ...(AllPermutations<Exclude<T, K>, O> extends infer U extends string[]
? U
: never)
]
: [
K, ...(AllPermutations<Exclude<T, K>, O> extends infer U extends string[]
? U
: never)
]
}[T]
type Join<T extends string[]> =
T extends [infer L extends string, ...infer R extends string[]]
? `${L}${Join<R>}`
: ""
type CreatePayloadString<T extends string[], P extends Record<string, any>> =
T extends [infer L extends string, ...infer R extends string[]]
? `<${L}>${P[L & keyof P]}</${L}>${CreatePayloadString<R, P>}`
: ""
type CondensedPayload = {
[K in AllPermutations<keyof Payload, OptionalProps<Payload>> as Join<K>]:
`<payload>${CreatePayloadString<K, Payload>}</payload>`
} extends infer O ? O[keyof O] : never
一些测试:
// Error
const payload1: CondensedPayload = '<payload><apiVersion>2.0</destination></payload>'
const payload2: CondensedPayload = '<payload><email>asd@asd.com</email></payload>'
const payload3: CondensedPayload = '<payload><apiVersion>2.0</apiVersion><email>asd@asd.com</email></payload>'
const payload4: CondensedPayload = '<payload><apiVersion>abc</apiVersion><destination>some string</destination></payload>'
// Valid
const payload4: CondensedPayload = '<payload><apiVersion>abc</apiVersion><destination>home</destination></payload>'
但说真的,对这样甚至更好的东西使用XML解析器:不要使用XML.
Playground