18

Is it possible to get a union type with all type values from an interface in typescript?

For example, when an interface is given as

interface A {
  a: string;
  b: () => void;
  c: number;
  d: string;
  e: 'something';
}

the result should be

type B = string | () => void | number | 'something';

I have no clue, how I would approach this problem, if it is even possible.

2 Answers 2

34

You can use keyof e.g.

 type B = A[keyof A] // will be string | number | (() => void)

The type something will not appear since the compiler does not differentiate between the type string and something - since both are strings it will omit it in the type B.

Sign up to request clarification or add additional context in comments.

3 Comments

Yeah, this works! But I actually wonder why. I have never read anywhere, that you can put a union type (keyof A) into the key brackets of an interface. Do you know, whether that is mentioned somewhere in the official docs?
@PeterLehnhardt There are two things going on here. Firstly, keyof returns the keys of A. Secondly, A['a'] will return the type of key a. So it maps over the keys to get their types.
Yes, your two things are actually clear to me. The only thing, which puzzles me, is that the identity A["a" | "b"] = A["a"] | A["b"] (which is basically a basic form of your answer) holds true and still does not seem to be mentioned anywhere in the typescript docs. And I think it's strange, that there does exist an unspoken rule in a language! What if there are other ones? How do I know about them? So my question was actually: Where did you find out about that rule?
1

You need something that is advance typescript.

Below example keyof A is completely interchangeable with string | () => void | number | 'something';. The difference is that if you add another property to A, say myfunc: string, then keyof A will automatically update to be string | () => void | number | something |myfunc. And you can use keyof in generic contexts like pluck, where you can’t possibly know the property names ahead of time. That means the compiler will check that you pass the right set of property names to pluck:

pluck(A, ['number ', 'unknown']); // error, 'unknown' is not in string | () => void | number | 'something';

It can be

let B :keyof A;

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.