在編寫Hack代碼時(shí),通常會(huì)啟動(dòng)文件<?hh并開始編寫代碼。但是,一個(gè)頂線實(shí)際上在Typechecker解釋代碼方面非常重要。
Hack文件中的代碼<?hh以其頂部的四個(gè)字符開頭,據(jù)說處于部分模式。這意味著typechecker會(huì)檢查一下它可以,但不再有; 它不堅(jiān)持全面覆蓋。部分模式很好用于開始逐漸輸入現(xiàn)有的代碼。以下是部分模式的規(guī)則:
<?hh
namespace Hack\UserDocumentation\TypeChecker\Modes\Examples\Partial;
use \Hack\UserDocumentation\TypeChecker\Modes\Examples\NonHack as NonHack;
// This function isn't type annotated, so callers will be able to do whatever
// they want with its result. However, the typechecker does still look at and
// check the body of the function.
function foo() {
$a = 1;
// This will geneate a type error:
// an int does not allow array append (Typing[4006])
$a[] = 2;
}
class A {
private int $x;
public function __construct() {
$this->x = 9;
}
public function getX(int $y): ?int {
return $y > 4 ? $this->x : null;
}
// You can even have non-type annotated code in the same class as
// type annotated code.
public function notTyped($z) {
return "Hello" . $z;
}
}
function bar(): int {
$a = new A();
// Not typechecked either. So we can pass an int and it will be converted to
// a string by the runtime, luckily.
echo $a->notTyped(3);
// The return value from this call is not typechecked since B is in a PHP
// file -- the typechecker assumes we know what we are doing since the
// annotation is missing.
$b = NonHack\B::getSomeInt();
echo NonHack\php_func(3, $b);
$i = $a->getX($b);
if ($i !== null) {
return $i;
} else {
return 0;
}
}
bar();
Output
string(4) "1004"
Hello33100
請(qǐng)注意,我們已經(jīng)注釋了一些代碼,但不是全部。無論該功能本身的注釋如何,都會(huì)檢查推送的代碼。
hack文件為:
<?hh // strict
意味著Typechecker在該文件中強(qiáng)制執(zhí)行嚴(yán)格的輸入規(guī)則。如果在所有可能的情況下,使用嚴(yán)格模式啟動(dòng)新項(xiàng)目 - 如果代碼庫中的每個(gè)文件都處于嚴(yán)格模式,則Typechecker的覆蓋范圍將最大化,因?yàn)樗鼘⒛軌蛲耆珯z查所有內(nèi)容,并且在運(yùn)行時(shí)不會(huì)出現(xiàn)類型錯(cuò)誤。
以下是嚴(yán)格模式的規(guī)則:
嚴(yán)格模式的是你想要的模式。整個(gè)Typechecker的好處是可以使用的,應(yīng)該確保零運(yùn)行時(shí)類型的錯(cuò)誤。
<?hh // strict
namespace Hack\UserDocumentation\TypeChecker\Modes\Examples\Strict;
use \Hack\UserDocumentation\TypeChecker\Modes\Examples\NonHack as NonHack;
function foo(): void {
$a = 1;
// This will generate a type error:
// an int does not allow array append (Typing[4006])
$a[] = 2;
}
class A {
private int $x;
public function __construct() {
$this->x = 9;
}
public function getX(int $y): ?int {
return $y > 4 ? $this->x : null;
}
// In partial, this didn't have to be annotated. In strict, it does.
public function notTyped(string $z): string {
return "Hello" . $z;
}
}
function bar(): int {
$a = new A();
// This is typechecked, so we can't pass an string-y int; we must pass a
// string
echo $a->notTyped("3");
// Cannot call these in strict mode:
// Unbound name:
// Hack\UserDocumentation\TypeChecker\Modes\Examples\NonHack\B
// (an object type) (Naming[2049])
$b = NonHack\B::getSomeInt();
// Unbound name:
// Hack\UserDocumentation\TypeChecker\Modes\Examples\NonHack\php_func
// Typing[4107])
echo NonHack\php_func(3, $b);
$i = $a->getX(100);
if ($i !== null) {
return $i;
} else {
return 0;
}
}
// This can't be in strict mode either. You need to put this in partial file
// and include it from this file. For the purposes of this example, though,
// we'll just suppress the error.
/* HH_FIXME[1002] So we can get interesting type-checking errors */
bar();
Output
string(4) "1004"
Hello33100
請(qǐng)注意,我們不能再調(diào)用該<?php文件,并且Hack文件中的所有實(shí)體都被注釋。
hack代碼為:
<?hh // decl
處于聲明模式。聲明模式代碼沒有類型檢查。然而,提取了在decl模式下的函數(shù),類等的簽名,并且在檢查其他代碼時(shí)被Typechecker使用。在轉(zhuǎn)換使用PHP編寫的代碼時(shí),聲明模式是最有用的:雖然該代碼的正文可能具有您不想立即處理的類型錯(cuò)誤,但仍然有益于使該代碼的簽名,至少其唯一存在,對(duì)其他代碼可見。事實(shí)上,Hack的一個(gè)非?;镜倪w移路徑是將所有<?php文件更改為decl模式,然后逐個(gè)開始采取每個(gè)文件并使其部分。
新的hack代碼應(yīng)該永遠(yuǎn)寫在DECL模式。
<?hh // decl
// Before this was <?php code. Now the typechecker can see the signatures of
// these functions and classes for when Hack calls them, even in strict mode.
namespace Hack\UserDocumentation\TypeChecker\Modes\Examples\Decl;
function php_func($x, $y) {
return $x . $y;
}
class B {
static function getSomeInt() {
return 100;
}
}
<?hh // strict
namespace Hack\UserDocumentation\TypeChecker\Modes\Examples\CallIntoDecl;
require __DIR__ . '/decl.inc.php';
// This actually makes the call to calling_into_decl() since we cannot have
// top level functions in strict mode
use \Hack\UserDocumentation\TypeChecker\Modes\Examples\Decl as Decl;
function calling_into_decl(): string {
// If php_func wasn't in decl mode, then we would get an unbound name error.
// As it is, we can call this function and the typechecker will ensure we are
// passing in the right number of arguments, but not the types of them.
return Decl\php_func("a", "b");
}
<?hh
namespace Hack\UserDocumentation\TypeChecker\Modes\Examples\CallIntoDecl;
var_dump(calling_into_decl());
Output
string(2) "ab"
該示例顯示所有三種模式。首先,它顯示一個(gè)以前存在的聲明模式文件<?php。除了標(biāo)題更改之外,沒有添加任何其他內(nèi)容。然后它顯示一個(gè)嚴(yán)格的模式文件調(diào)用到declare文件。Typechecker知道函數(shù)和類的簽名,并且可以確?;镜臇|西,例如是否調(diào)用命名實(shí)體并傳遞正確數(shù)量的參數(shù)。最后,我們有一個(gè)部分模式文件實(shí)際上以嚴(yán)格模式調(diào)用該函數(shù),因?yàn)槲覀儾荒茉趪?yán)格模式下進(jìn)行頂層函數(shù)調(diào)用。
如上例所示,模式可以自由混合; 您的項(xiàng)目中的每個(gè)文件可以處于不同的Typechecker模式。
更多建議: