Fabian Bosler
Fabian Bosler

Reputation: 2510

Difference between object type definitions in Typescript

We've been working on a larger project and different developers seem to use different type definitions for a fairly plane object, more precisely two versions stood out. Can anybody explain main differences, benefits, and implications of using either version?

type MyObject = { [_: string]: string | number }
type MyObjectAlternative = Record<string, string | number>

Cheers

Upvotes: 1

Views: 295

Answers (2)

There is a difference between both types.

type MyObject = { [_: string]: string | number }
type MyObjectAlternative = Record<string, string | number>

You can't use unions in MyObject ( in TypeScript before 4.4):

type MyObject = { [_: string | number ]: string | number } // error
type MyObjectAlternative = Record<'a'|'b', string | number> // ok

type MyObject = { [_: 'a'|'b' ]: string | number } // error
type MyObjectAlternative = Record<'a'|'b', string | number> // ok

An index signature parameter type cannot be a union type. Consider using a mapped object type instead

From T.4.4 (currently beta) you can use union as a type of a key in MyObject.

type MyObject = { [_: string | number | symbol]: string | number } // allowed
type MyObjectAlternative = keyof Record<'a' | 'b', string | number> // ok

type Keys = {
    [Prop in keyof MyObject]: Prop
}

type Keys2 = {
    [Prop in keyof MyObjectAlternative]: Prop
}

As you might have noticed, keyof MyObject and keyof MyObjectAlternative operators works differently in both cases.

MyObjectAlternative is more treated like regular object in javascript with all built in properties, while MyObject is treated as object without prototype.

Also, since TS 4.4 we can mix template literal strings:

type MyObject = { [_:  `data-${string}`]: string | number } // ok

But please keep in mind


type MyObject = { [_:  'a'|'b']: string | number } // error

union of literals still disallowed

Typescript 4.4

Upvotes: 1

Akxe
Akxe

Reputation: 11495

Record is the same as type literal. If you look at the definition of Record you will see this:

/**
 * Construct a type with a set of properties K of type T
 */
type Record<K extends keyof any, T> = {
    [P in K]: T;
};

Upvotes: 1

Related Questions