type DeepObjectToUniq<O extends object, Uniq extends unknown[] = [O]> = {
[P in keyof O]: O[P] extends object ? DeepObjectToUniq<O[P], [...Uniq, P]> : O[P]
} & {
readonly [uniq: symbol]: Uniq
}
Solution by 2083335157 #35035
思考一下子两个类型是否可以互相赋值? type A = { a: string } type B = { a: string; b?: string } 答案是可以的,并且A和B是不同的类型。完全符合本题要求。 但是有个问题是,上面的可选属性
b
是否可以定义一个不会属性污染的,答案是使用 unique symbol
那么思路就出来了,递归遍历所有对象,对每个加上可选的 unique symbol 的属性,但要注意,这个属性对应的值不能完全一样,不然 IsFalse<Equal<UniqBar["baz"], UniqFoo["baz"]>>
通过不了
declare const UniqKey: unique symbol;
type DeepObjectToUniq<T, Count extends any[] = [T]> = {
[P in keyof T]: T[P] extends Record<PropertyKey, any>
? DeepObjectToUniq<T[P], [...Count, P]>
: T[P];
} & {
[UniqKey]?: Count;
};
Solution by Vampirelee #32623
type DeepObjectToUniq<O extends object, _UniqFlag extends [PropertyKey?, object?] = []> =
{ [P in keyof O]: O[P] extends object ? DeepObjectToUniq<O[P], [P, O]> : O[P] }
& { [flag: symbol]: _UniqFlag } //为结构体打上独特的标志[字段名, 拥有者]
Solution by E-uler #24879
declare const KEY: unique symbol;
type DeepObjectToUniq<T extends object> = {
[K in keyof T]: T[K] extends object ? DeepObjectToUniq<T[K]> & { readonly [KEY]?: [T, K] } : T[K]
}
Solution by TKBnice #22948
declare const sym: unique symbol;
type DeepObjectToUniq<O extends object> = {
[K in keyof O]: O[K] extends object
? O[K] extends Function
? O[K]
: DeepObjectToUniq<O[K]> & { readonly [sym]?: [O, K] }
: O[K]
} & {
readonly [sym]?: unknown
}
Solution by milletlovemouse #21804
declare const KEY: unique symbol;
type DeepObjectToUniq<O extends object> = {
[K in keyof O]:
O[K] extends object
? DeepObjectToUniq<O[K]> & {readonly [KEY]?: [O, K]}
: O[K]
} & {readonly [KEY]?: [O]}
Learned a lot from others:
Keys are:
Solution by zhaoyao91 #20863
type DeepObjectToUniq<O extends object, U extends any[] = []> =
{ [x: symbol]: U}
&
{
[K in keyof O]: O[K] extends object
? DeepObjectToUniq<O[K], [O, K]>
: O[K];
}
Solution by logan70 #19235
type DeepObjectToUniq<O extends object, U extends any[] = [O]> = {
[key in keyof O]: O[key] extends object ? DeepObjectToUniq<O[key], [...U, key]> : O[key];
} & { [key in symbol]: U };
& { [key in symbol]: U };
don't understand this code??
Solution by CaoXueLiang #19053
// your answers
type DeepObjectToUniq<O extends object, K extends any[] = []> = {
[P in (keyof O | symbol)]: P extends keyof O ? O[P] extends object ? DeepObjectToUniq<O[P], [...K, O, P]> : O[P]
: K
}
Solution by Stan-BK #16492
// your answers
type DeepObjectToUniq<O extends object, U extends readonly any[] = [O]> = {
[K in keyof O]: O[K] extends object
? DeepObjectToUniq<O[K], [...U, K]>
: O[K]
} & { [K in symbol]: U }
Solution by humandetail #16444
// your answers
type DeepObjectToUniq<
O extends object,
U extends readonly any[] = [O]> =
{[J in keyof O]: O[J] extends object
? DeepObjectToUniq<O[J],[...U,J]>
: O[J]}
&{[K in symbol]:U} ;
Solution by justBadProgrammer #15865
type ToUnionOfFunction<T> = T extends any ? (x: T) => any : never;
type UnionToIntersection<U> = ToUnionOfFunction<U> extends (a: infer U) => any ? U : never
type DeepPick<T, S extends string> = UnionToIntersection<
S extends `${infer First extends keyof T & string}.${infer Rest}`
? { [K in First]: DeepPick<T[First], Rest> }
: S extends keyof T
? { [K in S]: T[S] }
: never
>
Solution by liuxing95 #12748
// your answers
type DeepObjectToUniq<O extends object> = {
[K in keyof O]: O[K] extends object
? DeepObjectToUniq<O[K] & { _?: [O, K] }>
: O[K];
};
Solution by SeptEarlyMorning #11909
type DeepObjectToUniq<O extends object,
Path extends Array<keyof any | object> = [O],
UniqueO = O & { readonly [Tag]?: Path }> =
{
[K in keyof UniqueO]: UniqueO[K] extends object ? (
DeepObjectToUniq<UniqueO[K], [...Path, K]>
) : UniqueO[K]
}
declare const Tag: unique symbol
Declare a unique symbol instead of using { [S in symbol]: Path }
Playground
Solution by teamchong #11436
// your answers
// the main idea is to add a unique {symbol: Path} to each property
type DeepObjectToUniq<O extends object, Path extends Array<unknown> = [O]> = O extends Record<keyof any, any> ? {
[K in keyof O]: DeepObjectToUniq<O[K], [...Path, K]>
} & {
[K in symbol] : Path
} : O;
Solution by Joyee691 #11416
const symbol = Symbol()
type DeepObjectToUniq<O extends object, Path extends any[] = [O]> = {
[K in keyof O]: O[K] extends object ? DeepObjectToUniq<O[K], [...Path, K]> : O[K]
} & { [symbol]?: Path }
Solution by Lionad-Morotar #9103
type DeepObjectToUniq<O extends object, Path extends any[] = [O]> = O extends Record<string,any> ? {
[key in keyof O]: DeepObjectToUniq<O[key],[...Path,key]>
} & {
[key in symbol]: Path
}: O
Solution by EGyoung #8637
// 553 - Deep object to unique
type Merge
Solution by Carefree-happy #7040
type Merge<T> = {
[P in keyof T]: T[P]
}
type DeepObjectToUniq<O extends object> = {
[P in keyof O]: O[P] extends object
? DeepObjectToUniq<Merge<O[P] & { _xxx?: [O, P] }>>
: O[P]
}
Solution by myNameIsDu #2832
// your answers
type DeepObjectToUniq<O extends object> = {
[k in keyof O]: O[k] extends object ? DeepObjectToUniq<O[k]> & { _uniq?: [O, k] } : O[k]
}
Solution by zongzi531 #2035
// your answers
type DeepObjectToUniq<O extends object> = {
[k in keyof O]: O[k] extends object ? DeepObjectToUniq<O[k]> & { _uniq?: [O, k] } : O[k]
}
Solution by emandirola #1163
type Key = string | number | symbol;
declare const KEY: unique symbol;
type DeepObjectToUniq<
O extends object,
Parent = O,
Path extends readonly Key[] = []
> = {
[K in keyof O]: O[K] extends object
? DeepObjectToUniq<O[K], O, [...Path, K]>
: O[K];
} & {
readonly [KEY]?: readonly [Parent, Path];
};
Solution by uid11 #581