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 valueobject
means any non-primitive value{}
is the same asObject
{ [k: string]: any }
is equivalent toRecord<string, any>
Record<K, T>
is a utility type to create mapped types. Often used for as a substitute for index signatures withRecord<string, any>
(shown above). Also can prescribe exact key/value pairs with something likeRecord<'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>
orRecord<string, any>
- To type any value, you should use
unknown
orany
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