Home > Back-end >  Why use index signature `{[key: string]: any}` instead of `object` type?
Why use index signature `{[key: string]: any}` instead of `object` type?

Time:06-29

I'm learning TypeScript and come across this use of index signatures in function parameters often. For eg,

export function template(resources: {[key: string]: any})

Since the value type is any, why is this type useful? And is it any different than passing object as the type?

CodePudding user response:

The object type is just a native js Object. It only has the functions and keys associated with the native Object.

So if you try to access a property of an object type, it will throw an error.

let b: object = {foo: 123};
b.foo; // Property 'foo' does not exist on type 'object'.(

But you can do the same with {[key: string]: any}

let a: {[key: string]: any} = {foo: 123};
a.foo;

You can do the same with Record<string, any>.

In fact, the Record type is declared as type Record<K extends string | number | symbol, T> = { [P in K]: T; }

CodePudding user response:

There are many ways to express 'objects', but consider the following examples. There is Object, object, {}, { [k: T]: U } and Record<K, T>. This is just because almost everything in JS (and by extension TS) is an object.*

I'll put the answer up-front with examples below:

  • Object means any non-nullish value
  • object means any non-primitive value
  • {} is the same as Object
  • { [k: string]: any } is equivalent to Record<string, any>
  • Record<K, T> is a utility type to create mapped types. Often used for as a substitute for index signatures with Record<string, any> (shown above). Also can prescribe exact key/value pairs with something like Record<'foo' | 'bar', 'baz' | 'bang'> being equivalent to { bar: "baz" | "bang"; foo: "baz" | "bang"; }
  • To type an empty object, it is recommended to use Record<string, never>
  • To type any object, you should use Record<string, unknown> or Record<string, any>
  • To type any value, you should use unknown or any

Examples

Consider the following about Object:

class C {}
const a: Object = 0
const b: Object = ""
const c: Object = []
const d: Object = {}
const e: Object = C
const f: Object = null // <-- error!
const g: Object = undefined // <-- error!
const h: Object = { foo: "bar" }
h.bar // Property 'foo' does not exist on type 'Object'.

Consider the following about object:

class C {}
const a: object = 0 // <-- error!
const b: object = "" // <-- error!
const c: object = []
const d: object = {}
const e: object = C
const f: object = undefined // <-- error!
const g: object = null // <-- error!
const h: object = { foo: "bar" }
h.bar // Property 'foo' does not exist on type 'object'.

Relevant Docs

Read about Record<K, T>.

Read about index signatures.

versus mapped types

  • Related