x1r15
x1r15

Reputation: 17

Accessing objects field using string in Typescript

I am having a class consisting of multiple public members.

for simplicity let's assume:

class ComponentData {
  id: number;
  type: ComponentType;
  location: ComponentLocation;
  label: string;
  value: number;
}

I do have a type defined:

type Layout = {[field in keyof ComponentData]?: InputSchema};

Using Object.keys(layout) I am displaying different set of inputs for different ComponentTypes. This works great, however later on input onChange I am trying to modify the source ComponentData.

function onPropertyChange(newValue: unknown, fieldName: string) {
    selectedItem[fieldName] = newValue;
}

I am receiving:

TS7053: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'ComponentData'.   No index signature with a parameter of type 'string' was found on type 'ComponentData'.

I tried to follow the solution suggested here: https://stackoverflow.com/a/66838662/8191341 as follows:

function onPropertyChange(newValue: unknown, fieldName: string) {
    const key = fieldName as keyof ComponentData;
    selectedItem![key] = newValue;
}

but then received:

TS2322: Type 'InputValues' is not assignable to type 'never'.   Type 'undefined' is not assignable to type 'never'.

Any ideas? :)

PS. Using //@ts-ignore it works as expected but I am not happy with the solution.

Upvotes: 0

Views: 826

Answers (1)

malarres
malarres

Reputation: 2946

I reproduced the error with this tsconfig [1] and this code solved the problem:

function onPropertyChange(newValue: unknown, fieldName: string) {
  Object.assign(selectedItem, { [fieldName]: newValue });
}

[1]

{
  "compilerOptions": {
    "target": "es2019",
    "module": "commonjs",
    "allowJs": false,
    "outDir": "./dist",
    "strict": true,
    "lib": ["es2019","DOM"],
    "typeRoots": ["node_modules/@types"],
    "esModuleInterop": true,
    "sourceMap": true
  },
  "include": ["src/**/*.ts"],
  "exclude": ["node_modules", "src/**/*.spec.ts"]
}

Upvotes: 1

Related Questions