spatie/typed

该软件包已被放弃,不再维护。没有建议的替代软件包。

用户空间中PHP类型系统的改进:泛型、类型化列表、元组和结构体

0.1.2 2020-11-20 08:48 UTC

This package is auto-updated.

Last update: 2021-02-20 09:24:31 UTC


README

Latest Version on Packagist Build Status StyleCI Quality Score Total Downloads

该软件包仅是关于PHP用户空间中可进行类型检查改进的一个简单概念证明。它增加了对类型推断、泛型、联合类型、类型化列表、元组和结构体的支持。由于所有操作都在用户空间中完成,因此对可用的语法有一些限制。

支持我们

68747470733a2f2f6769746875622d6164732e73332e65752d63656e7472616c2d312e616d617a6f6e6177732e636f6d2f74797065642e6a70673f743d31

我们投入了大量资源来创建最好的开源软件包。您可以通过购买我们的付费产品之一来支持我们。

我们非常感谢您从您的家乡给我们寄来明信片,并提及您正在使用我们的哪个软件包。您可以在我们的联系页面上找到我们的地址。我们将所有收到的明信片发布在我们的虚拟明信片墙上

安装

您可以通过composer安装该软件包

composer require spatie/typed

使用方法

类型推断

集合、元组和结构体都支持推断类型。这意味着所有示例都可以不手动指定类型而使用。例如

// This collection will only allow objects of type `Post` in it.
$postCollection = new Collection([new Post()]);

// This tuple will keep its signature of (Point, Point).
$vector = new Tuple(new Point(30, 5), new Point(120, 0));

// This struct's fields are autmoatically type checked.
$struct = [
    'foo' => new Post(),
    'bar' => function () {
        // ...
    },
];

以下示例都显示了手动类型配置。在某些情况下,类型推断不够用,您必须手动定义它们。您可能也喜欢手动方法,以便更清晰。

请注意,类型可能只部分推断。元组或结构体中的某些字段可能是类型定义,其他可能是实际值。未初始化的类型在读取时将抛出错误。

类型化列表和集合

$list = new Collection(T::bool());

$list[] = new Post(); // TypeError

在构造后,可以直接使用数据初始化一个集合。

$list = (new Collection(T::string()))->set(['a', 'b', 'c']);

该软件包还提供了一些预定义的列表作为快捷方式。

$list = new IntegerList([1, 4]);

$list[] = 'a'; // TypeError

泛型

泛型类型围绕类包裹,允许您为每个类不创建自定义类型。

$postList = new Collection(T::generic(Post::class));

$postList[] = 1; // TypeError

元组

$point = new Tuple(T::float(), T::float());

$point[0] = 1.5;
$point[1] = 3;

$point[0] = 'a'; // TypeError
$point['a'] = 1; // TypeError
$point[10] = 1; // TypeError

与列表类似,元组也可以使用set函数在构造后添加一些数据。

$tuple = (new Tuple(T::string(), T::array()))->set('abc', []);

结构体

$developer = new Struct([
    'name' => T::string(),
    'age' => T::int(),
    'second_name' => T::nullable(T::string()),
]);

$developer['name'] = 'Brent';
$developer['second_name'] = 'John';

$developer->set([
    'name' => 'BrenDt',
    'age' => 23,
    'second_name' => null,
]);

echo $developer->age;

$developer->name = 'Brent';

$developer->age = 'abc' // TypeError
$developer->somethingElse = 'abc' // TypeError

可空类型

可空类型可以通过两种功能上相同的方式定义

$list1 = new Collection(T::int()->nullable());

$list2 = new Collection(T::nullable(T::int()));

联合类型

联合类型意味着多个类型的集合。

$list = new Collection(T::union(T::int(), T::float()));

$list[] = 1;
$list[] = 1.1;

$list[] = 'abc'; // TypeError

联合类型也可以是可空的,并包含泛型。

不包括的内容

  • 正确的语法。
  • 泛型类型的IDE自动完成。
  • 防止标量类型之间的类型转换。
  • 在函数中为泛型类型提供类型提示。

创建自己的类型

可以使用 GenericTypeT::generic() 来创建该类型的结构。然而,也可以在不使用泛型的情况下创建自己的类型。以 Post 为例。泛型方法无需添加自定义类型即可工作。

$postList = new Collection(T::generic(Post::class));

$postList[] = new Post();
$postList[] = 1; // TypeError 

创建自己的类型时可以省略 generic 部分。

use Spatie\Typed\Type;
use Spatie\Typed\Types\Nullable;

class PostType implements Type
{
    use Nullable;
    
    public function validate($post): Post
    {
        return $post;
    }
}

现在您可以直接使用 PostType

$postList = new Collection(new PostType());

您也可以扩展 T 辅助器。

class T extends Spatie\Typed\T
{
    public static function post(): PostType
    {
        return new PostType();
    }
}

// ...

$postList = new Collection(T::post());

Nullable 特性添加了以下简单片段,以便在使用时使类型可空。

public function nullable(): NullType
{
    return new NullType($this);
}

注意:建议您在自己的类型类中实现 __toString

扩展数据结构

您可以自由扩展现有的数据结构。例如,您可以创建类似这样的简写元组

class Coordinates extends Tuple
{
    public function __construct(int $x, int $y)
    {
        parent::__construct(T::int(), T::int());

        $this[0] = $x;
        $this[1] = $y;
    }
}

我们为什么构建这个?

PHP 具有非常弱化的类型系统。这既是优点也是缺点。弱类型系统提供了一个非常灵活的开发平台,而强类型系统可以防止某些错误在运行时发生。

在其当前状态下,PHP 的类型系统尚未准备好实现许多人想要的一些特性。例如,查看一些提议更改当前类型系统的 RFC。

其中一些已经被拒绝,因为运行时性能问题或实现困难。此包是一个思想实验,假设这些特性在 PHP 中实现,并使用原生语法使用。

例如,以下语法会比此包的当前方式更受欢迎。

$postList = new Collection<Post>();

// vs.

$postList[] = new Collection(T::generic(Post::class));

无论如何,这些都是值得思考的问题。也许 PHP 的类型系统现在就很好?您可以在我的博客上了解更多关于类型安全的信息 在这里

贡献

有关详细信息,请参阅 CONTRIBUTING

安全

如果您发现任何与安全相关的问题,请通过电子邮件 freek@spatie.be 而不是使用问题跟踪器。

Postcardware

您可以自由使用此包,但如果它进入您的生产环境,我们非常希望您能从您的家乡寄给我们一张明信片,说明您正在使用我们的哪个包。

我们的地址是:Spatie,Kruikstraat 22,2018 安特卫普,比利时。

我们将所有收到的明信片 发布在我们的公司网站上

鸣谢

许可证

MIT 许可证(MIT)。有关更多信息,请参阅 许可证文件