open-index/open-npm huggingface dataset:
npm package: @jakobkg/shapes-ts
Description: Toy library to create runtime safe types in TS.
Latest version: 0.3.2

# shapes-ts

Toy library to create runtime safe types in TS.

When describing the shape of your data in shapes-ts, you get the corresponding
TS type and a validation utility for free!

```typescript
const CreditCategory = Shapes.enum(["director", "writer", "actor/actress"]);

const Credits = Shapes.object({
  category: CreditCategory,
  name: Shapes.string(),
});

const Movie = Shapes.object({
  title: Shapes.string(),
  rating: Shapes.number().where(
    (n) => n >= 0 && n <= 5,
    "rating must be in range 0.0-5.0",
  ),
  credits: Shapes.array(Credits),
});

// This infers as
// {
//   title: string,
//   rating: number,
//   credits: {
//     category: "director" | "writer" | "actor/actress",
//     name: string
//   }[]
// }
type Movie = Shapes.Type<typeof Movie>;

const movieData: unknown = getFromIMDB("tt23289160");

if (!Movie.check(movieData)) {
  throw new Error("Unexpected data from API");
}

// Past this point, movieData is typed as Movie

for (const credit of movieData.credits) {
  console.log(`${credit.name}: ${credit.category}`);
}
```

## Supported types

### Primitives

- string
- number
- boolean

...and literals of these

### Composite types

- object
- array
- tuple
- enum

### Modified types

- Nullable types (`T | null`)
- Optional types (`T | undefined`)
- Unions (`A | B`)
- Intersections (`A & B`)

## Predicates

Shapes can have additional validation checks added to them. These do not affect
the inferred type, but are still ran as part of a shape's `.check()` method to
help enforce constraints that are not easily modeled using the type system.

```typescript
const Username = Shapes.string().where(
  (str) => str.length < 10,
  "must be less than 10 characters long",
);

Username.check("jakob :)"); // true
Username.check("CptAmericaFan207"); // false
```

Predicates can be used with all types of shapes, and they may be combined both
by stacking them on a single shape and by combining shapes that already have
predicates on them.

```typescript
const Fizz = Shapes.number().where(
  (n) => n % 3 === 0,
  "must be divisible by 3",
);

const Buzz = Shapes.number().where(
  (n) => n % 5 === 0,
  "must be divisible by 5",
);

const FizzBuzz = Fizz.and(Buzz);

Fizz.check(3); // true
FizzBuzz.check(3); // false
Fizz.check(5); // false
Buzz.check(5); // true
FizzBuzz.check(15); //true
```