Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to replace `object` with `Record<string, unknown>`?

Consider this:

interface Foo {
  foo: string;
}

const foo: Foo = { foo: "foo" };

function bar(obj: object) {}                   // <--- ERROR 1
bar(foo);

function baz(obj: Record<string, unknown>) {}
baz(foo);                                      // <--- ERROR 2

So, ERROR 1 is:

Don't use `object` as a type. The `object` type is currently hard to use ([see this issue](https://github.com/microsoft/TypeScript/issues/21732)).
Consider using `Record<string, unknown>` instead, as it allows you to more easily inspect and use the keys.eslint@typescript-eslint/ban-types

Hence, I did what I have been told me and replaced object by Record<string, unknown> in baz. But, now I get ERROR 2:

Argument of type 'Foo' is not assignable to parameter of type 'Record<string, unknown>'.
  Index signature for type 'string' is missing in type 'Foo'.ts(2345)

So, what's the proper approach to avoid using object?

like image 367
user3612643 Avatar asked Sep 06 '25 04:09

user3612643


2 Answers

This is currently a known issue with TypeScript.

You should change Foo to be a type instead of an interface:

type Foo = {
  foo: string
};

const foo: Foo = { foo: "foo" };

function baz(obj: Record<string, unknown>) {}
baz(foo);                   

Edit: If you don't have any control over the interface, you can use this utility type created by Younho Choo on the aforementioned GitHub issue thread:

interface Foo {
  foo: string;
}

type IndexSignature<O extends object> = {
  [P in keyof O]: O[P]
};

const foo: IndexSignature<Foo> = { foo: "foo" };

function baz(obj: Record<string, unknown>) {}
baz(foo); 

This avoids using any which some developers consider bad practice (although I'd argue it's perfectly acceptable practice in TmTron's answer).

TypeScript Playground

like image 152
Luke Carr Avatar answered Sep 07 '25 19:09

Luke Carr


When you use Record<string, any>, you don't get the error.
Just be aware that the object values are of type any instead of unknown: see 'unknown' vs. 'any'

interface Foo {
  foo: string;
}

const foo: Foo = { foo: "foo" };

function fct(obj: Record<string, any>) {}
fct(foo);

Typescript Playground

like image 20
TmTron Avatar answered Sep 07 '25 19:09

TmTron