0

I'm trying to use typed object value as key for another object, but TS seems to loose its type and evaluate it as string.

Is it by design? Are there any way to get targetObj with keys' of type SomeKey?

Link to playground

type SomeKey = "A" | "B"

const Obj = {
    "A": "A"
} as { [k in SomeKey]: SomeKey }

type A = typeof Obj.A

// TargetObj ---> { [x: string]: string } instead of { [k in SomeKey]: SomeKey }
const TargetObj = {
    [Obj.A]: "str"
}

EDIT

As Alexey L. correctly pointed out out the problem lies in difference between {[k in SomeKey]: SomeKey} and {[k in SomeKey]: k}

But can anybody explain how it works?

1 Answers1

0

In order for TypeScript to recognize your TargetObj as a { [k in SomeKey]: SomeKey } it must satisfy [k in SomeKey]. To do this, you must exhaust all possible values of SomeKey. This can only be done manually as [Obj.A]: "A" on its own cannot satisfy this. Additionally, [Obj.A]: "A", [Obj.B]: "B" won't do it either, as it cannot guarantee that they are the correct values. I tried [Obj.A as A]: "A", ... as well, but it doesn't work because, although it can guarantee the type, cannot guarantee the value.

If all you need is for the value to be the same as the key, this gets a whole lot easier as TypeScript gives you the ability to assert that they are the same.

type SomeKey = "A" | "B";

type ObjType = { [k in SomeKey]: k };

const Obj: ObjType = {
    A: "A",
    B: "B",
};

type A = typeof Obj.A;
type B = typeof Obj.B;

const TargetObj: ObjType = {
    [Obj.A]: "A",
    [Obj.B]: "B",
};
Brandon Dyer
  • 1,316
  • 12
  • 21
  • Not sure I understood what you mean. The trick is indeed was in `{ [k in someKey]: k }` instead of `{ [k in SomeKey]: SomeKey }` and it was pointed out earlier. Anyway thanks for answer! – walkthroughthecode Dec 25 '19 at 09:37