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

@total-typescript/shoehorn

Package Overview
Dependencies
Maintainers
1
Versions
3
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@total-typescript/shoehorn

Work seamlessly with partial mocks in TypeScript.

  • 0.1.0
  • Source
  • npm
  • Socket score

Version published
Weekly downloads
37K
decreased by-6.81%
Maintainers
1
Weekly downloads
 
Created
Source

shoehorn

shoehorn lets you pass partial data in tests, while keeping TypeScript happy.

type Request = {
  body: {
    id: string;
  };
  // Imagine oodles of other properties...
};

it("Should get the user", () => {
  // Even though we only care about body.id for
  // this test, we need to pass in the whole Request
  // object
  getUser({
    body: {
      id: "123",
    },
  } as Request);
});

'as' in tests feels bad.

  • You're trained not to use it
  • You need to manually specify the type you want to assert to
  • For testing with incorrect data, you need to 'double-as' (as unknown as User)

shoehorn gives you some first-class primitives for safely providing incomplete data to tests.

import { fromPartial } from "@total-typescript/shoehorn";

it("Should get the user", () => {
  getUserId(
    fromPartial({
      body: {
        id: "123",
      },
    }),
  );
});

But isn't passing partial data to tests bad?

Yes, in general. Having to pass huge objects to tests is a sign that your types are too loose. Ideally, every function should only specify the data it needs.

Unfortunately, we live in the real world. There are many cases where shoehorn is the best choice:

  • Legacy codebases: If you're working on a large codebase, you might not have the time to refactor everything to be perfect.
  • Third-party libraries: If you're using a third-party library, you might not be able to alter the types without needless wrapper functions.

API

For each example below, imagine that the following types are defined:

type Request = {
  body: {
    id: string;
  };
  // Imagine oodles of other properties...
};

// The function we're testing
const requiresRequest = (request: Request) => {};

fromPartial

Lets you pass a deep partial to a slot expecting a type.

import { fromPartial } from "@total-typescript/shoehorn";

requiresRequest(
  fromPartial({
    body: {
      id: "123",
    },
  }),
);

It'll fail if you pass a type that doesn't match the one expected:

// Type "1234123" has no properties in common
// with type 'PartialObjectDeep<Request>'
requiresRequest(fromPartial("1234123"));

fromAny

Lets you pass anything to a slot, while still giving you autocomplete on the original type:

import { fromAny } from "@total-typescript/shoehorn";

requiresRequest(
  fromAny({
    body: {
      id: 124123,
    },
  }),
);

It WILL NOT FAIL if you pass something that doesn't match.

// All good!
requiresRequest(fromPartial("1234123"));

fromExact

A convenience method for forcing you to pass all the properties of a type. Useful for when you want to swap in and out of fromPartial/fromAny:

import { fromExact } from "@total-typescript/shoehorn";

requiresRequest(
  // Will fail! We're not passing all the oodles of
  // properties of Request
  fromExact({
    body: {
      id: 124123,
    },
  }),
);

FAQs

Package last updated on 11 Apr 2023

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