Home > Blockchain >  how to initialize a typescript interface with a variable key
how to initialize a typescript interface with a variable key

Time:01-09

See the following code:

function createObj(key: string, value:unknown) {
  const obj = {};
  obj[key] = value;
  return obj;
}

gives 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 '{}'.

I know I could write it as

  const obj = {} as Record<string, unknown>;

but I wonder if I could initialize the object in one statement, like

  const obj = {
    key: value
  };

which does not work because key is a string literal here and not the value of variable key.

CodePudding user response:

One can use computed property names (referenced by another answer) as follows:

function createObj(key: string, value: unknown) {
  return {
    [key]: value,
  };
}

CodePudding user response:

WHen you create literal empty object on the fly, TS forbids you to add any properties to it, because according to inference, it should be empty. I am talking about this line:

  const obj = {};

Hence, in order to make it in TS way, you need to infer provided arguments:


function createObj<Key extends PropertyKey, Value>(key: Key, value: Value): Record<Key, Value>
function createObj<Key extends PropertyKey, Value>(key: Key, value: Value) {
  const obj: Partial<Record<Key, Value>> = {};
  obj[key] = value;
  return obj;
}

const result = createObj('a', 1)
result.a // number

Key - represents infered type of key argument

Value - represents infered type of value argument

I used Partial<Record<Key, Value>> type for obj. For Partial and Record see docs.

Partial - all values are optional

Record - represents a hash map data structure (regular object in javascript)

As you might have noticed, result.a infered as a number.

We can do better. Just add type Json:

type Json =
  | null
  | undefined
  | string
  | number
  | Array<Json>
  | { [prop: string]: Json }

function createObj<Key extends PropertyKey, Value>(key: Key, value: Value): Record<Key, Value>
function createObj<Key extends PropertyKey, Value>(key: Key, value: Value) {
  const obj: Partial<Record<Key, Value>> = {};
  obj[key] = value;
  return obj;
}

const result = createObj('a', 1)
result.a // 1

Now, result.a is 1

  • Related