-
Notifications
You must be signed in to change notification settings - Fork 12.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How to implement n-ary Extract? #23413
Comments
Not sure about this.. but maybe: type BrandKey<T,Brand> = {[K in keyof T]: Brand}
type CheckKey<K, This, Brands> =
K extends keyof Brands ?
(This extends Brands[K] ? never : K)
: never;
type Check<T extends [any,string], Brands> = T extends {} ?
CheckKey<keyof T[0], T[1], Brands> : never;
type PreventCollisionsInner<A, B, C, D, E, F, G, H> =
Check<
[A, "A"] |
[B, "B"] |
[C, "C"] |
[D, "D"] |
[E, "E"] |
[F, "F"] |
[G, "G"] |
[H, "H"],
BrandKey<A, "A"> &
BrandKey<B, "B"> &
BrandKey<C, "C"> &
BrandKey<D, "D"> &
BrandKey<E, "E"> &
BrandKey<F, "F"> &
BrandKey<G, "G"> &
BrandKey<H, "H">
>;
type CatchError<T, Pass> = [T] extends [never] ? Pass : ("Error " & [T]);
type PreventCollisions<A = {}, B = {}, C = {}, D = {}, E = {}, F = {}, G ={}, H = {}> =
CatchError<PreventCollisionsInner<A, B, C, D, E, F, G, H>,
A & B & C & D & E & F & G & H>; |
I think you need variadic types to do this right, but I've experimented with the same idea and a hacky way to accomplish something very similar is: type ArrayKeys = keyof any[]
type Indices<T> = Exclude<keyof T, ArrayKeys>
type GetUnionKeys<U> = U extends Record<infer K, any> ? K : never
type CombineUnion<U> = { [K in GetUnionKeys<U>]: U extends Record<K, infer T> ? T : never }
type Combine<T> = CombineUnion<T[Indices<T>]>
declare function combine<
T extends object[] &
{
[K in Indices<T>]: {
[K2 in keyof T[K]]: K2 extends GetUnionKeys<T[Exclude<Indices<T>, K>]> ? never : any
}
} & { "0": any }
>(objectsToCombine: T): Combine<T>
const result1 = combine([{ foo: 534 }, { bar: "test" }])
const error1 = combine([{ foo: 534, dupKey: "dup1" }, { bar: "test", dupKey: "dup2" }]) The key is the |
@kpdonn Man, that is some crazy type level programming. What would this look like with variadic types? |
One thing is you'd be able to use rest parameters instead of manually passing an array. Besides that I don't know for sure since they aren't implemented yet and most of the discussion about them in #5453 happened before conditional types or even mapped types existed, but I'm hoping they'll be similarly flexible to work with. |
Automatically closing this issue for housekeeping purposes. The issue labels indicate that it is unactionable at the moment or has already been addressed. |
I built a tiny library that makes mixins typesafe, including detecting method collisions at compile time. The implementation is really simple, and it's a nicer API than the one in the TS handbook, I think.
I'm having trouble extending it to support more than a few parameters passed to
mixin(A, B, C)
, because I have to test all permutations forExtract
to work:Extract<keyof A, keyof B>
Extract<keyof A, keyof B | keyof C>
Extract<keyof A | keyof C, keyof B>
Extract<keyof A, keyof B | keyof C | keyof D>
Extract<keyof A | keyof D, keyof B | keyof C>
Extract<keyof A | keyof C, keyof B | keyof D>
Extract<keyof A | keyof C | keyof D, keyof B | keyof D>
This quickly explodes and gets really branchy, making the
PreventCollisions
type (below) really unwieldy.Any suggestions for how to avoid this branchieness, to support more params? The thing I'd like to express is "What are the keys that shapes A, B, C ... Z have in common?"
The issue tracker is not the best place for questions like these, but I thought TS maintainers would be interested to see this solution. Feel free to close if you feel otherwise :)
Code is here: https://github.com/bcherny/magical-mixin/blob/master/src/index.ts.
Relevant section is:
The text was updated successfully, but these errors were encountered: