2

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?

user3612643
  • 5,096
  • 7
  • 34
  • 55
  • Just use `object` and disable your linter rule for it, unless you actually run into the "hard to use" scenario to which it refers. – jcalz Oct 06 '21 at 19:48

2 Answers2

3

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

Luke Carr
  • 553
  • 5
  • 18
  • The problem is that `Foo` and the likes are coming from 3rd party libraries I have no control about :-( – user3612643 Oct 06 '21 at 09:16
  • @user3612643 I've added an alternative solution to my answer that supports interfaces coming from 3rd party libraries. – Luke Carr Oct 07 '21 at 12:33
2

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

TmTron
  • 17,012
  • 10
  • 94
  • 142