Typescript conversion from interface to recursive type throws an Index signature is missing in type error

Viewed 53

Live Example

I have defined a recursive SerializableRecord interface that I defined with the help of recursive type references. This interface can be changed.

type Serializable =
  | string
  | number
  | boolean
  | null
  | undefined
  | SerializableArray
  | SerializableRecord;

interface SerializableArray extends Array<Serializable> {}
interface SerializableRecord extends Record<string, Serializable> {}

I have another imported interface (which means I can't change it):

interface ExternalInterface {
   attr: string;
}

Now if I try to do the following I get an error:

const x: ExternalInterface = {attr: 'a'};
const y: SerializableRecord = x;
// Throws a TS error: "Index signature is missing in type 'ExternalInterface'"
   

Is there a way to make those two entities compatible, without introducing any or unknown?

2 Answers

This behavior is currently by design according to this GitHub issue.

The best workaround I know of is to “convert” the interface into a type:

type AsType<T> = { [P in keyof T]: T[P]; }

const x: ExternalInterface = {attr: 'a'};
const y: SerializableRecord = x as AsType<typeof x>;

Another one is to use the object spread syntax,

const y: SerializableRecord = { ...x };

but that requires copying the object, which you probably do not want to do.

this should work, but doesn't satisfy your requirement of not changing the ExternalInterface

type ExternalInterface = { attr: string };
const x: ExternalInterface = { attr: 'a' };
const y: SerializableRecord = x;
Related