5

I'm trying to make a type with one string being an object, but every other string key equal to a string. Here's all the code that I've tried.

interface SubElement {
  someProperty: string;
}

This is the object type that I want in the 'subElement' property of the main object.

interface MainType1 {
  [key: string]: string;
  /* Error: Property 'subElement' of type 'SubElement' is not assignable to 'string' index type 'string'.ts(2411) */
  subElement: SubElement; 
}

This one errors within the interface declaration, and it also errors as a type instead of an interface.

type MainType3 = {
  /* Error: Property 'subElement' of type 'SubElement' is not assignable to 'string' index type 'string'.ts(2411) */
  subElement: SubElement; 
  [key: Exclude<string, 'subElement'>]: string;
}

This has the same error as the first one.

/* Type doesn't error */
type MainType2 = {
  subElement: SubElement;
} & {
  [key: string]: string;
}

/* Error: Type '{ subElement: { someProperty: string; }; }' is not assignable to type 'MainType2'.
  Type '{ subElement: { someProperty: string; }; }' is not assignable to type '{ [key: string]: string; }'.
    Property 'subElement' is incompatible with index signature.
      Type '{ someProperty: string; }' is not assignable to type 'string'.ts(2322) */
let someVar: MainType2 = { 
  subElement: {
    someProperty: ''
  }
}

This one errors when I try to initialize anything with that type, since it's expecting 'subElement' to be a string.

/* Type doesn't error */
type MainType4 = {
  subElement: SubElement;
} & {
  [key: Exclude<string, 'subElement'>]: string;
}

/* Error: Type '{ subElement: { someProperty: string; }; }' is not assignable to type 'MainType2'.
  Type '{ subElement: { someProperty: string; }; }' is not assignable to type '{ [key: string]: string; }'.
    Property 'subElement' is incompatible with index signature.
      Type '{ someProperty: string; }' is not assignable to type 'string'.ts(2322) */
let otherVar: MainType4 = {
  subElement: {
    someProperty: ''
  }
}

Same error as before, 'subElement' is expected to be a string.

Is this possible or do I need something like {[key: string]: string | SubElement}?

  • 1
    See [this question](https://stackoverflow.com/q/61431397/438273). As a workaround, you can use a function which asserts the type internally from a starting input value of the parts which don't match the index signature: https://tsplay.dev/w2En4W – jsejcksn Dec 21 '21 at 04:50
  • There is no such type as `string & not "subElement"` and no way to represent your desired object shape as a specific type. See [the answer to the other question](https://stackoverflow.com/a/61434547/2887218) for the various workarounds and approaches. – jcalz Dec 21 '21 at 04:50

0 Answers0