Home > Blockchain >  how to convert Array<A> | Array<B> to Array<A | B> in Typescript
how to convert Array<A> | Array<B> to Array<A | B> in Typescript

Time:10-02

I have a type like the following:

type Schema = {
 name: string;
 status: "Active" | "Blocked";
}

And I have created the following Typescript Function:

type ConvertSchema<T> = {
 [key in keyof T]?: T[key] | T[key][];
}

I want to convert "Schema" type to "ConvertedSchemaCorrect" as following:

// This is exptected
type ConvertedSchemaCorrect = {
 name?: string | string[];
 status?: "Active" | "Blocked" | ("Active" | "Blocked")[]
}

// This is not expected (Typescript produces this)
type ConvertedSchemaInvalid = {
 name: string | string[]
 status: "Active" | "Blocked" | "Active"[] | "Blocked"[]
}

CodePudding user response:

This works:

type ConvertSchema<T> = {
  [key in keyof T]?: T[key] | T[key][];
};

type ConvertedSchema = ConvertSchema<Schema>;

const x: ConvertedSchema = {
  name: ['foo', 'bar'],
  status: ['Active', 'Blocked']
}

NB it's [key in keyof T] not [key in T]. Your version doesn't compile at all for me (using TypeScript 4.4.3): I get "Type 'T' is not assignable to type 'string | number | symbol'."

CodePudding user response:

As already pointed out in comments, you're missing a keyof in the mapped type declaration: you have to give it a set of keys, not the object itself:

type ConvertSchema<T> = {
 [key in keyof T]?: T[key] | T[key][];
}

That caused 3 TS errors, and probably that was what made the compiler misbehave (though I'm not quite sure how did it manage to give a type at all based on something it doesn't even understand).


You can also ensure that if one of the keys is an array, the other keys also have to be arrays (if that's what you want) by using something like this:

type ConvertSchema<T> = T | {
 [key in keyof T]?: T[key][];
}

Playground Link

  • Related