Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
April 19, 2023 11:00 am GMT

TypeScript Type Negation: How to Forbid Certain Properties

Type negation in TypeScript allows you to create types that explicitly exclude certain properties. Usually, we define types that specify what properties an object must have to satisfy that type. With type negation, we want to do the opposite: We specify which properties an object must not have. You can think of this as reserved properties.

Let's consider the following example. We have a generic createItem function that inserts a new item into our NoSQL database (e.g. MongoDB, DynamoDB, etc.). The NoSQL database and its tables do not have a defined column schema, that means the item with all its properties is stored as is. However, in order to retrieve the items, we need to define at least one property as a primary key (e.g. in DynamoDB this is the hash key). This is usually an ID as an integer or UUID, which can be defined either by the database or the application.

function createItem<TItem extends object>(item: TItem): TItem {  // Database sets ID  const newItem = db.insert(item);  return newItem;}// Returns object with id { id: "0d92b425efc9", name: "John", ... }const user = createItem({ name: "John", email: "[email protected]" });

We can call this function with any JavaScript object and store it in our NoSQL database. But what happens if the object we pass in contains an id property?

// What will happen?//> Will it create a new item?//> Will it overwrite the item if it exists?const user = createItem({ id: "0d92b425efc9", name: "John", email: "[email protected]" });

What actually happens depends on the database, of course. A new item could be created, or an existing item could be overwritten, or even an error could be thrown if we are not supposed to specify an external ID. Of course, we can simply add a check to the id property and raise an error ourselves to prevent such cases.

function createItem<TItem extends object>(item: TItem): TItem {  if('id' in item) throw new Error("Item must not contain an ID");  // Database sets ID  const newItem = db.insert(item);  return newItem;}// Throws an errorconst user = createItem({ id: "0d92b425efc9", name: "John", email: "[email protected]" });

Let's go one step further and use TypeScript generics and types to prevent such cases from happening in the first place. We simply forbid the item to contain an id property.

type ReservedKeys = {  id: string;}function createItem<TItem extends object>(  item: TItem extends ReservedKeys ? never : TItem): TItem {  if('id' in item) throw new Error("Item must not contain an ID");  // Database sets ID  const newItem = db.insert(item);  return newItem;}

In this example we define a ReservedKeys type with forbidden keys. These are the properties that should not be allowed for the item. In the function signature, we then use TItem extends ReservedKeys to check if the generic TItem is a subset of ReservedKeys. If it is, we set the element type to the special value never.

Let's go back to our previous example. Now what happens when we specify an object with ID?

// What will happen?//> TypeScript error: Argument of type '{ id: string; name: string; email: string; }' is not assignable to parameter of type 'never'const user = createItem({ id: "0d92b425efc9" name: "John", email: "[email protected]" });

TypeScript reports an error that the object we passed to the function doesn't match the expected type.

TypeScript Playground

TypeScript Playground

Of course, we should never rely on static type checking alone to avoid such errors. Checking the property id at runtime within the implementation should always be present. The type negation is rather syntactic sugar to catch possible errors already at compile time and to have a function signature that matches the implementation.

I hope you found this post helpful. If you have any questions or comments, feel free to leave them below. If you'd like to connect with me, you can find me on LinkedIn or GitHub. Thanks for reading!


Original Link: https://dev.to/zirkelc/typescript-type-negation-how-to-forbid-certain-properties-42d9

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To