1

After getting the error unions can't be used in index signatures, use a mapped object type instead I am now attempting to convert a string literal union (key names of an interface) to a mapped object, as explained here. https://github.com/microsoft/TypeScript/issues/24220#issuecomment-390063153

But it still isn't working:

const returnObject: { 
   [index : mappedObjectOfConfigDataKeys] : Partial<ConfigData>
 } = {...accumulator};

// error TS1023: An index signature parameter type must be either 'string' or 'number'.

// 51 [index : // mappedObjectOfConfigDataKeys] : // Partial<ConfigData>
//     ~~~~~


 if (currentStepInstance.hasSaveableData && currentStepInstance.configDataKey) {
    returnObject[currentStepInstance.configDataKey] = validatedUserInput;
 } 
// error TS7053: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{}'.
//  No index signature with a parameter of type 'string' was found on type '{}'.

// 55  returnObject[currentStepInstance.configDataKey] = validatedUserInput;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

To prove the prior issue:

const returnObject: { 
   [index : stringLiteralUnion] : Partial<ConfigData>
 } = {...accumulator};

// (parameter) index: stringLiteralUnion
// An index signature parameter type cannot be a union type. Consider using a mapped object type instead.ts(1337)

Anyone know how to fix this? These last two attempts have me in circles. The compiler seems to want the mapped object to pass a constrained set of strings; I don't know how to give it that in an acceptable way.

export default interface ConfigData {
   languageCode : string
   , numberOfRepeats : number
   , projectId : string
}

/**** Index Signature handling for the above interface ****/
export type stringLiteralUnion = "languageCode" | "numberOfRepeats" | "projectId";

export type mappedObjectOfConfigDataKeys = {[key in stringLiteralUnion]: string}; 
// also tried typing it as `any` as shown in the linked post
// same error occured

Typescript Playground

Link to TS Playground

Update 1

Attempted:

const returnObject: Record<keyof ConfigData, Partial<ConfigData>> = {...accumulator};

Error message:

const returnObject: Record<"languageCode" | "numberOfRepeats" | "projectId", Partial<ConfigData>>

Type '{ languageCode?: string | undefined; numberOfRepeats?: number | undefined; projectId?: string | undefined; }' is not assignable to type 'Record<"languageCode" | "numberOfRepeats" | "projectId", Partial<ConfigData>>'.

  Types of property 'languageCode' are incompatible.
    Type 'string | undefined' is not assignable to type 'Partial<ConfigData>'.
      Type 'undefined' is not assignable to type 'Partial<ConfigData>'.ts(2322)

Update 2

Attempted:

const returnObject: Record<"languageCode" | "numberOfRepeats" | "projectId", Partial<ConfigData>> = {...accumulator};

Error:

const returnObject: Record<"languageCode" | "numberOfRepeats" | "projectId", Partial<ConfigData>>

Type '{ languageCode?: string | undefined; numberOfRepeats?: number | undefined; projectId?: string | undefined; }' is not assignable to type 'Record<"languageCode" | "numberOfRepeats" | "projectId", Partial<ConfigData>>'.

  Types of property 'languageCode' are incompatible.
    Type 'string | undefined' is not assignable to type 'Partial<ConfigData>'.
      Type 'undefined' is not assignable to type 'Partial<ConfigData>'.ts(2322)

Sean D
  • 3,810
  • 11
  • 45
  • 90
  • what are you trying to achieve? you want an object with the same keys as `ConfigData`, and what is supposed to be the values? could you provide a link to typescript playground or something? – D Pro Jul 04 '20 at 13:04
  • @DPro The goal is to clear the two errors on both of the statements in the 1st code block. I think it will involve typing `returnObject`'s index signature string values correctly (it may be something else though). I've posted a link to a TS playground above – Sean D Jul 04 '20 at 13:16

2 Answers2

0

not sure what you are trying to achieve:

const returnObject: Record<keyof ConfigData, Partial<ConfigData>> = {...accumulator};
D Pro
  • 1,756
  • 1
  • 8
  • 15
0

Instead of typing the index signature to a mapped object, I needed to convert the value to a mapped type.

This line:

const returnObject: { 
   [index : mappedObjectOfConfigDataKeys] : Partial<ConfigData>
 } = {...accumulator};

becomes this:

const returnObject: Partial<ConfigData> = accumulator;
Sean D
  • 3,810
  • 11
  • 45
  • 90