Tip
Put every .tyhp file you want compiled on an include glob in tyhp.json. That is how the compiler finds sources.
Tier 0 · Story 10Complete
Tyhp does not use PHP's include, require, include_once, or require_once as language statements in Tyhp source. Those constructs always produce TYHP4801 (CheckerIncludeNotAllowed). There is no import keyword. Discover source with tyhp.json include globs, reference types with use, and load emitted PHP at runtime with Composer autoload (the emitter can inject the autoloader into entry points).
The compiler's file set comes from tyhp.json, not from include statements in .tyhp files.
{
"include": ["./src/**/*.tyhp"],
"exclude": ["./vendor/**", "./build/**"],
"tyhpdefInclude": ["./tyhpdef/**/*.tyhpdef"],
"output": {
"path": "./build",
"phpVersion": "8.4",
"strictTypes": true
}
}
include / exclude — globs of .tyhp (and optionally .php) files to parse, bind, check, and emittyhpdefInclude / tyhpdefExclude — type-definition files consumed for checking only (no PHP output)Every matching file is in the compilation unit. Symbols are visible across files via namespaces and use statements; you do not need to "include" one Tyhp file from another.
Emitted PHP is ordinary PHP. Runtime loading uses Composer PSR-4 (and autoload.files for namespace _functions.php files). Enable build.updateComposer if you want the compiler to write/merge composer.json in the output directory.
An entry point is a Tyhp source file with top-level executable code (code outside class, function, or namespace declarations). The emitter writes those as standalone PHP files. build.entryPointAutoloader (for example { "composer": "vendor/autoload.php" }) makes the emitter prepend a require_once for the autoloader. Per-file override: declare(autoload='composer'|'none'|path).
<?tyhp
declare(output_file='public/index.php');
declare(autoload='composer');
App\Application $app = new App\Application();
$app->run();
You cannot write require_once 'vendor/autoload.php' in Tyhp source — that is TYHP4801. The emitter injects the autoloader into the PHP output when autoload is configured.
declare(output_file=…)declare(output_file='public/index.php') routes the code that follows to a specific path under output.path, instead of the default PSR-4 layout. Use it for front controllers, CLI scripts, and other files that must live at a fixed location. The directive is stripped from the PHP output.
When the emitter processes source files, it splits them into PSR-4-compliant output units. Each class, interface, trait, or enum declaration gets its own output file. Namespace-level functions are grouped into a single _functions.php per namespace. Top-level executable code (entry points) is emitted as standalone files.
<?tyhp
// File: src/Models.tyhp
namespace App\Models;
class User {
public function __construct(
public string $name,
public string $email
): void {}
}
class Post {
public function __construct(
public string $title,
public User $author
): void {}
}
The above single source file produces two PHP output files:
<?php
// Output: build/src/Models/User.php
declare(strict_types=1);
namespace App\Models;
class User {
public function __construct(
public string $name,
public string $email
) {}
}
<?php
// Output: build/src/Models/Post.php
declare(strict_types=1);
namespace App\Models;
use App\Models\User;
class Post {
public function __construct(
public string $title,
public User $author
) {}
}
Output paths follow the type's fully-qualified name (and output.path / output.namespacePrefix). The psr4 config key feeds generated Composer autoload mappings; it does not remap emit folders.
tyhp.json.use.require_once.eval()eval() is discouraged. Using it produces info diagnostic TYHP4800. Set build.allowEval to true in tyhp.json to silence that diagnostic. Code inside eval() is not type-checked. Prefer ordinary Tyhp/PHP modules and Composer autoload.
Put every .tyhp file you want compiled on an include glob in tyhp.json. That is how the compiler finds sources.
Use use statements for types and functions. The binder resolves symbols across all files in the project; you do not include one Tyhp file from another.
Configure build.entryPointAutoloader (and declare(autoload=…) when needed) so entry-point PHP receives require_once for Composer. Do not write require / include in Tyhp source.
Use declare(output_file='path') when a file must be emitted at a specific location (public index, CLI binary).
Use PSR-4 namespace conventions for classes. The emitter produces one output file per class, following the type's namespace path.
Don't write include, require, include_once, or require_once in Tyhp source. They always error with TYHP4801. There is no import keyword either — use use plus Composer autoload plus tyhp.json include globs.
Don't wrap declarations in a casual or mismatched existence check (e.g. if (!\class_exists('Foo')) with a short name inside a namespace). Declaration gates are supported, but Tyhp requires the gate argument to be the exact fully-qualified name of what you declare — see Declaration Gating.
Don't use eval() unless you have a hard requirement. It is info TYHP4800 unless build.allowEval is true, and the evaluated string is not type-checked.
<?tyhp
// ERROR TYHP4801 — include/require is not allowed in Tyhp
// require 'config/database.tyhp';
// require_once 'vendor/autoload.php';
// include_once 'helpers/math.tyhp';
Discover those files with include globs, use the types you need, and let the emitter inject the autoloader on entry points:
<?tyhp
declare(output_file='public/index.php');
declare(autoload='composer');
use App\Application;
Application $app = new Application();
$app->run();