1

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

5
  • 1
    The first line is a literal implementation of the second one, you can check it by looking for definition of Record. Commented Jul 15, 2021 at 11:55
  • 1
    I believe Record was something Typescript didn't initially have, so creating simple types for Objects used the first version. IOW: it could be partially legacy reasons the first version exists. Edit, just checked, it wasn't until version 2.1 the Record type was introduced. typescriptlang.org/docs/handbook/release-notes/… Commented Jul 15, 2021 at 11:57
  • Thx guys, are there advantages of using one version over another? Commented Jul 15, 2021 at 12:06
  • 1
    Only code readability, I would say the Record is just a tad easier, before using it, I always seemed to have to lookup again how to do it. Since using Record I've not needed too. Commented Jul 15, 2021 at 12:20
  • @Cerberus these both types are different. In Record, you can use a union of strings to represent keys, while in MyObject you can't use unions Commented Jul 15, 2021 at 13:48

2 Answers 2

1

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

Sign up to request clarification or add additional context in comments.

3 Comments

This is wrong, they are the same, see the definition of Record. In your second example, you used string | number for type literal, but for Record you used strings only. This type T1 = { [_:n any ]: string | number } is wrong, but this: type T2 = { [_ in string | number ]: any }, is ok.
@Akxe In your exmaple T1 is not the same as T2 or T3. I don't understand what you mean. Keys and Keys2 was provided to show how keyof operator works with different types. Because Record differs from indexed type, Keys and Keys2 are completely different. Please hover you mouse on both of them
1

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;
};

1 Comment

It is not the same, because to define Record you use [P in K] while to define indexed object you use [prop: string].

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.