0

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.

1
  • 1
    const obj: Record<string, unknown> = { [key]: value } Commented Jan 9, 2023 at 8:14

2 Answers 2

1

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

function createObj(key: string, value: unknown) {
  return {
    [key]: value,
  };
}
Sign up to request clarification or add additional context in comments.

Comments

1

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.