fredemmott/type-assert

This package is abandoned and no longer maintained. The author suggests using the hhvm/type-assert package instead.

Convert untyped data to typed data

v1.1.1 2017-08-14 23:59 UTC

README

Hack library for converting untyped data to typed data.

Usage

TypeAssert provides several static methods that take a mixed input, and will either return it unmodified (but with type data) or throw an exception; for example:

<?hh // strict
use \FredEmmott\TypeAssert\TypeAssert;
function need_string(string $bar): void {
}

function main(): void {
  needs_string(TypeAssert::isString('foo')); // type-safe and works fine
  needs_string(TypeAssert::isString(123)); // type-safe, but throws
}

These include:

  • isString(mixed): string
  • isInt(mixed): int
  • isFloat(mixed): float
  • isBool(mixed): bool
  • isResource(mixed): resource
  • isNum(mixed): num
  • isArrayKey(mixed): arraykey
  • isNotNull<T>(?T): T
  • isInstanceOf<T>(classname<T>, mixed): T
  • isClassnameOf<T>(classname<T>, mixed): classname<T>
  • matchesTypeStructure<T>(TypeStructure<T>, mixed): T

matchesTypeStructure<T>(TypeStructure<T>, mixed): T

Asserts that a variable matches the given type structure; these can be arbitrary nested shapes. This is particular useful for dealing with JSON responses.

<?hh // strict
class Foo {
  const type TAPIResponse = shape(
    'id' => int,
    'user' => string,
    'data' => shape(
      /* ... */
    ),
  );

  public static function getAPIResponse(): self::TAPIResponse {
    $json_string = file_get_contents('https://api.example.com');
    $array = json_decode($json_string, /* associative = */ true);
    return TypeAssert::matchesTypeStructure(
      type_structure(self::class, 'TAPIResponse'),
      $array,
    );
  }
}

You can use type_structure() to get a TypeStructure<T> for a type constant, or ReflectionTypeAlias::getTypeStructure() for top-level type aliases.

WARNING

TypeStructure<T>, type_structure(), and ReflectionTypeAlias::getTypeStructures() are experimental features of HHVM, and not supported by Facebook or the HHVM team. This means that matches_type_structure() may need to be removed in a future release.

matches_type_structure() iis based on these APIs anyway as there is not currently a viable alternative.

isNotNull<T>(?T): T

Throws if it's null, and refines the type otherwise - for example:

<?hh // strict
use \FredEmmott\TypeAssert\TypeAssert;

function needs_string(string $foo): void {}
function needs_int(int $bar): void {}

function main(?string $foo, ?int bar): void {
  needs_string(TypeAssert::isNotNull($foo)); // ?string => string
  needs_int(TypeAssert::isNotNull($bar)); // ?int => int
}

isInstanceOf<T>(classname<T>, mixed): T

Asserts that the input is an object of the given type; for example:

<?hh
use \FredEmmott\TypeAssert\TypeAssert;

class Foo {}

function needs_foo(Foo $foo): void {}

function main(mixed $foo): void {
  needs_foo(TypeAssert::isInstanceOf(Foo::class, $foo));
}

main(new Foo());

isClassnameOf<T>(classname<T>, mixed): classname<T>

Asserts that the input is the name of a child of the specified class, or implements the specified interface.

<?hh // strict
use \FredEmmott\TypeAssert\TypeAssert;

class Foo {
  public static function doStuff(): void {}
}
class Bar extends Foo {
  <<__Override>>
  public static function doStuff(): void {
    // specialize here
  }
}

function needs_foo_class(classname<Foo> $foo): void {
  $foo::doStuff();
}

function main(mixed $class): void {
  needs_foo_class(TypeAssert::isClassnameOf(Foo::class, $class));
}

main(Bar::class);

Credit

This library is a reimplementation of ideas from:

  • @admdikramr
  • @ahupp
  • @dlreeves
  • @periodic1236
  • @schrockn

Security Issues

We use GitHub issues to track public bugs. Please ensure your description is clear and has sufficient instructions to be able to reproduce the issue.

Facebook has a bounty program for the safe disclosure of security bugs. In those cases, please go through the process outlined on that page and do not file a public issue.

License

Type-Assert is BSD-licensed. We also provide an additional patent grant.