KiaraGrouwstra / typical

playground for type-level primitives in TypeScript
MIT License
173 stars 5 forks source link

Swap keys #4

Closed goodmind closed 7 years ago

goodmind commented 7 years ago

Do you know how to write type like this one?

type Swap<T> = ...

type A = { a: 'b', c: 'd' }
type B = Swap<A> // { b: 'a', d: 'c' }
KiaraGrouwstra commented 7 years ago

Tried for a bit, here's what I came up with:

export type Obj<T> = { [k: string]: T };
export type UnionHasKey<Union extends string, K extends string> = ({[S in Union]: '1' } & Obj<'0'>)[K];
export type If<Cond extends '0'|'1', Then, Else> = { 1: Then, 0: Else }[Cond];

type A = { a: 'b', c: 'd' };

type Keys = keyof A; // "a" | "c"
type Vals = A[keyof A]; // "b" | "d"
type y = {[P1 in Vals]: {[P2 in keyof A]: If<UnionHasKey<A[P2], P1>, P2, never> }[Keys] }; // { b: "a"; d: "c"; }

type Swap<
    T extends { [k: string]: string },
    Keys extends keyof T = keyof T,
    Vals extends string = T[Keys]
> = {[P1 in Vals]: {[P2 in Keys]: If<UnionHasKey<T[P2], P1>, P2, never> }[Keys]};

type B = Swap<A>;

Still fails in playground, though I think master should have fixed most issues like this. Haven't managed to test that way yet, but yeah.

goodmind commented 7 years ago

@tycho01 wow, still trying to figure out how things in this repo ever works

KiaraGrouwstra commented 7 years ago

Haha :), I just try step by step too, but yeah, it looks more complex when put together. To sorta illustrate what's going on:

SimonMeskens commented 7 years ago

Nice one! :)

I kinda gave up after

type strT = {
    [key: string]: string
}

type Swap<T extends strT> = {
    [N in T[keyof T]]: ???
}

type A = { a: 'b', c: 'd' }
type B = Swap<A>