Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@fp51/opaque-type

Package Overview
Dependencies
Maintainers
4
Versions
237
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@fp51/opaque-type

Functional opaque type api for Typescript and Javascript

  • 1.0.0-canary-14f2d8bb8556877bf47ffafd2c0fc81e19c4d2f7-1619124540405
  • refs/heads/dependabot/npm_and_yarn/types/jest-26.0.22-14f2d8bb8556877bf47ffafd2c0fc81e19c4d2f7
  • Source
  • npm
  • Socket score

Version published
Weekly downloads
37
decreased by-86.79%
Maintainers
4
Weekly downloads
 
Created
Source

@fp51/opaque-types

Continuous integration

Inspired from https://codemix.com/opaque-types-in-javascript/

Usage

npm add @fp51/opaque-type

📖 Documentation

Why ?

Semantic type checking

The following naive code will compile properly, except that if you mix createRoom parameters you will introduce a nasty bug at runtime.

type RoomID = string;
type UserID = string;

function createRoom(roomId: RoomID, userId: UserID) {
  // something
}

const roomId: RoomID = ...;
const userId: UserID = ...;
createRoom(userId, roomId);

Opaque at rescue !

This following code won't compile, because Opaque add more specificty to RoomId and UserId, so typescript wont think they are compatible because they are built uppon a string;

import { Opaque } from "@fp51/opaque-type";

type RoomID = Opaque<"RoomId">;
type UserID = Opaque<"UserId">;

function createRoom(roomId: RoomID, userId: UserID) {
  // something
}

const roomId: RoomID = ...;
const userId: UserID = ...;

createRoom(userId, roomId); // TypeError

Here the error message you will get in your editor or when you will try to build your application

Argument of type 'Opaque<"UserId">' is not assignable to parameter of type 'Opaque<"RoomId">'.
  ...

Type opacification (hence the name)

Let say you built a nice piece of code:

// message.ts
type Message = {
  userId: string,
  text: string,
};

export function clearMessageText(message: Message) : Message {
  return message.text = '';
}

export function getMessage():Message {
  return ...
}

You user can endup writting the following code:

import { clearMessageText, getMessage } from './message';

const message = { userId: 'userId', text: 'mytext' };

clearMessageText(message); 

or

import { getMessage } from '..'

const message2 = getMessage();

message2.userId = 'whatever';

Those two pieces of code are problematic, because in these the inner structure of your types are exposed and manipulated.

If you make any change to the Message structure it will be a breaking change for your code user. Meaning that he could find himself to edit dozen or hundreds of line of code.

How can we avoid this protecting our user from creating a code strongly tied to your library internals ?

// message.ts
import { createOpaqueAPI } from '../index';

type $Message = {
  userId: string,
  text: string,
};

const { toOpaque, fromOpaque } = createOpaqueAPI<
  'Message',
  $Message,
>('Message');

type Message = ReturnType<typeof toOpaque>;

export function getMessage(): Message {
  return toOpaque({ userId: 'userId', text: 'text' });
}

export function clearMessageText(message: Message): Message {
  const $message = fromOpaque(message)

  return toOpaque({
    ...$message,
    text: '',
  });
}

Your user won't be able to write code in same fashion, he will have to ignore the internals of your code.

import { getMessage, clearMessageText } from '../index';

const message = getMessage();

const messageCleared = clearMessageText(message); 

This is especially usefull when creating a reusable a library:

  • It does protect the user of your code from himself
  • It does protect you the maintainer by allowing you to break type structure behind the scène without creating a breaking change.

Keywords

FAQs

Package last updated on 22 Apr 2021

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc