1

In TypeScript I know how to declare a multiple key-value pairs object

{ [key: string]: any }

How can I declare a single key-value pair?

The specific use-case I want to support is a prop that can be an array of either string or a single key-pair object.

For example:

const searchArray = [
  'name', 
  {stats: 'resolution'},
  'uptime',
  {config: 'interface'},
];

At first I thought the solution was simply

Record<string,string>

So the final declaration for my searchArray would be

interface Props {
  (...)
  searchArray: (string | Record<string,string>)[],
}

But I expect it to reject this because I sent two key-pair in an object but it accepts it.

searchArray={[
 'name',
 'bitrate',
 {stats:'resolution', stats:'frameRate'}
]}

It should accept only one key-pair per object. The following should be accepted

searchArray={[
 'name',
 'bitrate',
 {stats:'resolution'}, 
 {stats:'frameRate'}
]}

Thanks!

  • [Type for object that has one and only one property](https://stackoverflow.com/q/56469951/12299000), or [typescript restrict count of object's properties](https://stackoverflow.com/q/39190154/12299000). – kaya3 Dec 18 '22 at 00:14

1 Answers1

3

AFAIK there's no way to restrict a string-indexed type to having only one property entry, but here are two alternative suggestions:

  1. Use a tuple:

TS Playground

type Entry<Key extends PropertyKey, Value> = [Key, Value];

const searchArray = [
  'name', 
  ['stats', 'resolution'],
  'uptime',
  ['config', 'interface'],
] satisfies (string | Entry<string, string>)[];

  1. Or — slightly more verbose (but perhaps more clear, depending on your perspective) — use an object type with key and value properties:

TS Playground

type Entry<Key extends PropertyKey, Value> = {
  key: Key;
  value: Value;
};

const searchArray = [
  'name', 
  { key: 'stats', value: 'resolution' },
  'uptime',
  { key: 'config', value: 'interface' },
] satisfies (string | Entry<string, string>)[];

See also: generics in the TS handbook

jsejcksn
  • 27,667
  • 4
  • 38
  • 62
  • Thanks, you seem to know a lot! Are you one of the developers of Typescript? But the two solutions are different than my original writeup. In the first solution uses an array [] instead of object {}. In the second solution key and value properties were added. Are you saying it's impossible to represent with Typescript? – the constant gardener Dec 10 '22 at 01:52
  • [^](https://stackoverflow.com/questions/74707608/typescript-what-is-the-typing-for-a-single-key-pair-value/74707707?noredirect=1#comment131926046_74707707) @theconstantgardener Well... an [array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) is an object! It's just an object with unique attributes (e.g. it uses number type keys (non-negative integers) to index its collection values instead of string type keys). The first example uses a tuple (an array with a fixed number of elements) to represent your constraint. – jsejcksn Dec 10 '22 at 02:25
  • [^](https://stackoverflow.com/questions/74707608/typescript-what-is-the-typing-for-a-single-key-pair-value/74707707?noredirect=1#comment131926046_74707707) @theconstantgardener "_Is it impossible?_" I don't think it's possible. When you use `string` as a property key index type, it necessarily means that "all values that can be assigned to `string` are allowed as property keys" (which means all strings — not just a specific one!), so the second suggestion addresses that by only allowing two types of keys: `key` and `value`, each holding its respective part of data from the entry pair. – jsejcksn Dec 10 '22 at 02:31