Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Define a list of optional keys for Typescript Record

I want to type an object which can only have keys 'a', 'b' or 'c'.

So I can do it as follows:

Interface IList {     a?: string;     b?: string;     c?: string; } 

They are all optional! Now I was wondering if this can be written with Record in just one line

type List = Record<'a' | 'b' | 'c', string>; 

The only issue is that all keys need to be defined. So I ended up with

type List = Partial<Record<'a' | 'b' | 'c', string>>; 

This works, but I can imagine there is a better way to do this without Partial. Is there an other way to make the keys optional inside Record ?

like image 441
Jeanluca Scaljeri Avatar asked Nov 13 '18 08:11

Jeanluca Scaljeri


People also ask

How do I make my properties optional in TypeScript?

In the TypeScript, Partial<T> is implemented as below; it makes properties optional. type Partial<T> = { [P in keyof T]?: T[P]; };

What is record <> in TypeScript?

TypeScript Records are a great way to ensure consistency when trying to implement more complex types of data. They enforce key values, and allow you to create custom interfaces for the values. The TypeScript Record type was implemented in TypeScript 2.1, and takes the form Record<K, T> .

What does Keyof do in TypeScript?

keyof is a keyword in TypeScript which is used to extract the key type from an object type.


2 Answers

There is no way to specify the optionality of members of Record. They are required by definition

type Record<K extends keyof any, T> = {     [P in K]: T; // Mapped properties are not optional, and it's not a homomorphic mapped type so it can't come from anywhere else. }; 

You can define your own type if this is a common scenario for you:

type PartialRecord<K extends keyof any, T> = {   [P in K]?: T; }; type List =  PartialRecord<'a' | 'b' | 'c', string> 

Or you can define PartialRecord using the predefined mapped types as well:

type PartialRecord<K extends keyof any, T> =  Partial<Record<K, T>> 
like image 184
Titian Cernicova-Dragomir Avatar answered Oct 14 '22 10:10

Titian Cernicova-Dragomir


You can create the partial version of your List type:

type PartialList = Partial<List>; 

And you could do it all on one line if you don't want the intermediate type:

type PartialList = Partial<Record<'a' | 'b' | 'c', string>>; 

You might decide that, in the end, the most expressive for your future self is:

type List = {     a?: string;     b?: string;     c?: string; } 
like image 40
Fenton Avatar answered Oct 14 '22 11:10

Fenton