fredemmott / type-assert
Requires
- hhvm: ^4.0
- hhvm/hsl: ^4.0
Requires (Dev)
- facebook/fbexpect: ^2.0.0
- hhvm/hacktest: ^1.0
- hhvm/hhast: ^4.0
- hhvm/hhvm-autoload: ^2.0
README
用于将无类型数据转换为有类型数据的黑客库。
关于 TypeAssert::matches_type_structure()
的警告
TypeStructure<T>
、type_structure()
和 ReflectionTypeAlias::getTypeStructures()
是 HHVM 的实验性功能,不受 Facebook 或 HHVM 团队支持。这意味着 matches_type_structure()
可能在未来版本中未经警告就被移除。
由于目前没有可行的替代方案,matches_type_structure()
基于这些 API。
安装
composer require hhvm/type-assert
使用
TypeAssert 提供接受混合输入的函数,要么返回未修改的输入(但带有类型数据),要么抛出异常;例如
<?hh // strict use namespace Facebook\TypeAssert; function needs_string(string $bar): void { } function main(): void { needs_string(TypeAssert\string('foo')); // type-safe and works fine needs_string(TypeAssert\string(123)); // type-safe, but throws }
包括以下内容
string(mixed): string
int(mixed): int
float(mixed): float
bool(mixed): bool
resource(mixed): resource
num(mixed): num
arraykey(mixed): arraykey
not_null<T>(?T): T
instance_of<T>(classname<T>, mixed): T
classname_of<T>(classname<T>, mixed): classname<T>
matches_type_structure<T>(TypeStructure<T>, mixed): T
强制转换
TypeAssert 还包含 Facebook\TypeCoerce
命名空间,其中包含类似的一组函数
string(mixed): string
int(mixed): int
float(mixed): float
bool(mixed): bool
resource(mixed): resource
num(mixed): num
arraykey(mixed): arraykey
match_type_structure<T>(TypeStructure<T>, mixed): T
这些将执行“安全”转换,例如将“类似整数”的字符串转换为整数,将整数转换为字符串,将数组转换为向量,将数组转换为字典等。
类型规范
您还可以断言/强制转换复杂数据类型(除了形状和元组),而不需要 type_structure
<?hh use namespace Facebook\TypeSpec; $spec = TypeSpec\dict( TypeSpec\string(), TypeSpec\int(), ); $x = $spec->assertType(dict['foo' => 123]); // passes: $x is a dict<string, int> $x = $spec->assertType(dict['foo' => '123']); // fails $x = $spec->assertType(dict[123 => 456]); // fails $x = $spec->assertType(dict[123 => 456]); // fails $x = $spec->coerceType(dict[123 => '456']); // passes: $x is dict['123' => 456];
不支持形状和元组,因为它们无法用泛型表示。
matches_type_structure<T>(TypeStructure<T>, mixed): T
断言变量与给定的类型结构匹配;这些可以是任意嵌套的形状。这对于处理 JSON 响应特别有用。
<?hh // strict use namespace Facebook\TypeAssert; 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\matches_type_structure( type_structure(self::class, 'TAPIResponse'), $array, ); } }
您可以使用 type_structure()
获取类型常量的 TypeStructure<T>
,或使用 ReflectionTypeAlias::getTypeStructure()
获取顶层类型别名。
not_null<T>(?T): T
如果它是 null,则抛出异常,否则细化类型 - 例如
<?hh // strict use namespace \Facebook\TypeAssert; function needs_string(string $foo): void {} function needs_int(int $bar): void {} function main(?string $foo, ?int bar): void { needs_string(TypeAssert\not_null($foo)); // ?string => string needs_int(TypeAssert\not_null($bar)); // ?int => int }
is_instance_of<T>(classname<T>, mixed): T
断言输入是给定类型的对象;例如
<?hh use namespace Facebook\TypeAssert; class Foo {} function needs_foo(Foo $foo): void {} function main(mixed $foo): void { needs_foo(TypeAssert::is_instance_of(Foo::class, $foo)); } main(new Foo());
is_classname_of<T>(classname<T>, mixed): classname<T>
断言输入是指定类的子类或实现了指定接口的名称。
<?hh // strict use namespace Facebook\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::is_classname_of(Foo::class, $class)); } main(Bar::class);
信用
这个库是对以下想法的重新实现:
- @admdikramr
- @ahupp
- @dlreeves
- @periodic1236
- @schrockn
安全问题
我们使用GitHub问题来跟踪公共漏洞。请确保您的描述清晰,并包含足够的说明以便能够重现问题。
Facebook有一个赏金计划,用于安全地披露安全漏洞。在这些情况下,请按照该页面上概述的程序进行,不要提交公共问题。
许可
类型断言是MIT许可的。