0

I would like to convert an object type to a comma separated string of its keys.

With input

type Obj = {
  val1: string;
  val2: string;
  val3: string;
}

I want the output

type ObjKeys = GetObjKeys<Obj>;
// 'val1,val2,val3'

Is this possible to obtain?

I'm trying to get a better type safety for an api middle layer I'm building. With an expected output certain fields should be fetched, and those should be typed in a specific manner for it to work. I like to make it mandatory to fetch the fields necessary to populate the expected output type. In that way trying to minimise possible errors.

  • 1
    Allthough its possible, it is not something you want to do. The order of properties inside of object types is not intended to be observed by the type system. You can convert the union of keys to a tuple which is shown here: https://stackoverflow.com/questions/55127004/how-to-transform-union-type-to-tuple-type and then join the tuple elements. But you really should consider an alternative. – Tobias S. Dec 15 '22 at 11:43

1 Answers1

0

If the order of comma separated keys sequence is not important, you can create the type that you want like this :

type CreateCommaSeparatedType<T extends string, K extends string = T> = 
 [T] extends [never] 
    ? "" 
    : K extends any 
        ? Exclude<T, K> extends never
            ? `${K}` 
            : `${K},${CreateCommaSeparatedType<Exclude<T, K>>}` 
        : "";

So if you declare a type based on CreateCommaSeparatedType:

type CommaSepreatedType = CreateCommaSeparatedType<keyof Obj>;

CommaSepreatedType will be :

"val1,val2,val3" | "val1,val3,val2" | "val2,val1,val3" | "val2,val3,val1" | "val3,val1,val2" | "val3,val2,val1"

Remember that due to the recursive and permuting essence of CreateTypeCommaSeparated, the number of unions becomes huge very easily as the number of Obj keys gets more. So this may cause a typescirpt error which says :

Expression produces a union type that is too complex to represent.

But if the order of comma separated keys sequence matters, you can do it as @Tobias S. mentioned in the comment.

mahooresorkh
  • 1,361
  • 2
  • 8
  • 16