将 darray 存储到 Shape 中时出现不一致错误
Inconsistent error while storing a darray into a Shape
我有这样的身材
const type TFileInfo = shape(
'displayName' => string,
'givenName' => string,
'jobTitle' => string,
'businessPhones' => vec<string>
);
private Person::TFileInfo $person;
现在我的 class 构造函数看起来像这样
public function __construct(string $apiresponse) { // instance method
$json = \json_decode($response, /* associative = */ true);
TypeAssert\matches<self::TFileInfo>($json);
$this->person = $json; //OFFENDING LINE
$this->person['businessPhones1'] = "";
}
奇怪的是上面的代码没有抛出任何错误。
如果我删除有问题的行,那么最后一行会引发编译时错误 没有预期,因为字段 'businessPhones1' 未在此形状类型中定义,并且此形状类型没有允许未知字段
我在这里错过了什么?有没有更好的方法将 API 响应分配给类型变量?
TypeAssert\matches
不能证明它的参数是你指定的类型,这与其他一些 built-ins 的行为形成对比,比如 is_null
是 special-cased类型检查器。相反,它强制参数和 returns 它,所以你需要将你的独立调用移动到赋值,即 $this->person = TypeAssert\matches<self::TFileInfo>($json);
.
你可能预料到 $this->person = $json
赋值会出现类型错误,但实际上 json_decode
和其他一些不安全的 built-in PHP 函数是 special-cased 由类型检查器确定为底层类型(可转换为任何类型),因此它们可以在 type-assert 之前完全可用。今天仍然如此:请参阅 its type definition in the HHVM source,可能是为了兼容性。
关于此案例的另一个有趣的地方是 $this->person = $json
将 $this->person
强制转换为底部类型以及绑定的下游。据我了解,这是 Hack 类型检查器的一种特定行为,它针对单层 属性 嵌套执行此操作,但它保留了属性属性的类型(第二个示例 has_error
):
<?hh // strict
class Box<T> { public function __construct(public T $v) {} }
function no_error<T>(Box<int> $arg): T {
$arg->v = json_decode('');
return $arg->v;
}
function has_error<T>(Box<Box<int>> $arg): T {
$arg->v->v = json_decode('');
return $arg->v->v;
}
我有这样的身材
const type TFileInfo = shape(
'displayName' => string,
'givenName' => string,
'jobTitle' => string,
'businessPhones' => vec<string>
);
private Person::TFileInfo $person;
现在我的 class 构造函数看起来像这样
public function __construct(string $apiresponse) { // instance method
$json = \json_decode($response, /* associative = */ true);
TypeAssert\matches<self::TFileInfo>($json);
$this->person = $json; //OFFENDING LINE
$this->person['businessPhones1'] = "";
}
奇怪的是上面的代码没有抛出任何错误。
如果我删除有问题的行,那么最后一行会引发编译时错误 没有预期,因为字段 'businessPhones1' 未在此形状类型中定义,并且此形状类型没有允许未知字段
我在这里错过了什么?有没有更好的方法将 API 响应分配给类型变量?
TypeAssert\matches
不能证明它的参数是你指定的类型,这与其他一些 built-ins 的行为形成对比,比如 is_null
是 special-cased类型检查器。相反,它强制参数和 returns 它,所以你需要将你的独立调用移动到赋值,即 $this->person = TypeAssert\matches<self::TFileInfo>($json);
.
你可能预料到 $this->person = $json
赋值会出现类型错误,但实际上 json_decode
和其他一些不安全的 built-in PHP 函数是 special-cased 由类型检查器确定为底层类型(可转换为任何类型),因此它们可以在 type-assert 之前完全可用。今天仍然如此:请参阅 its type definition in the HHVM source,可能是为了兼容性。
关于此案例的另一个有趣的地方是 $this->person = $json
将 $this->person
强制转换为底部类型以及绑定的下游。据我了解,这是 Hack 类型检查器的一种特定行为,它针对单层 属性 嵌套执行此操作,但它保留了属性属性的类型(第二个示例 has_error
):
<?hh // strict
class Box<T> { public function __construct(public T $v) {} }
function no_error<T>(Box<int> $arg): T {
$arg->v = json_decode('');
return $arg->v;
}
function has_error<T>(Box<Box<int>> $arg): T {
$arg->v->v = json_decode('');
return $arg->v->v;
}