TypeLang

Specimen sheetType language for PHPPHP 8.1+

The type syntax of PHPDoc,
parsed.

TypeLang is a declarative type language inspired by PHPStan and Psalm. It describes the types you already write in doc-comments — int[], array<string, T>, Foo::CONST_*, T is U ? A : B — and ships the parts to work with them: a parser, a printer, a reflection reader and a PHPDoc parser. The tree below is drawn by a JavaScript port of the reference parser. Type a type.

0 tokens0 nodesdepth 0

PrettyTypePrinter


    

§ 01

One type, grown.

Every construct in the language composes with every other. Start from a name and keep wrapping.

  1. A name

    Any identifier is a type: a built-in, a class, an alias. TypeLang checks that a type is well-formed, not that it exists — resolution is a separate concern.

    Basic types ↗
  2. Nullable

    A leading question mark wraps the type in a NullableTypeNode. It binds tighter than |, so ?A|B is (?A)|B.

    Logical types ↗
  3. Template arguments

    Angle brackets carry generics. Any type goes inside, trailing commas are fine, and * stands for “whatever”.

    Generic types ↗
  4. Union

    Unions are flat: A|B|C is one node with three children, not two nested pairs. Intersections use & and bind tighter.

    Logical types ↗
  5. Keys

    A second argument describes the key. array-key, int, literal strings — the parser doesn't care which; your tool decides what they mean.

    Generic types ↗
  6. Shape

    Braces turn a name into a shape: named fields, each with its own type. Keys can be identifiers, numbers, quoted strings or class constants.

    Shape types ↗
  7. Ranges and unsealed shapes

    int<1, max> is just a generic with two literal-ish arguments. The trailing ... says “more keys may follow”.

    Shape types ↗
  8. Optional fields

    A question mark after the key marks the field optional. Notice how little of the tree has to move.

    Shape types ↗
  9. Callable

    Any name followed by parentheses is a callable type. Parameters may be named, variadic, by-reference or optional; the return type follows a colon.

    Callable types ↗
  10. Generic callables and conditions

    Callables can declare template parameters with of, super and defaults. The return type here is conditional: T is Paid ? Receipt : null.

    Conditional types ↗

§ 02

Vocabulary.

Every construct the grammar knows, set as a specimen. Hover a bracket to see the node behind it.

Names

Nullable

Union

Intersection

Generics

Variance hints

Wildcard argument

Legacy list

Offset access

Literals

Constants and masks

Shapes

Callables

Generic callables

Conditional

$this

§ 03

Strict subsets.

Every grammar construct is a flag on TypeParserFeatures. Switch some off and the parser rejects the syntax with a message that says why. Native PHP types only? Turn everything off but names.


    

§ 04

Coverage.

83 syntactic constructs, each fed to every tool's own parser. A construct counts when the parser returns a node carrying what was written — not a silently truncated one.

TypeLang type-lang/parser 2.x82/83
PHPStan phpstan/phpdoc-parser 2.369/83
phpDocumentor type-resolver 2.062/83
Psalm vimeo/psalm 6.540/83
Phan phan/phan 5.531/83

Full table with the verdict for every construct, per tool, in the syntax comparison ↗. Two tools answer even where they did not understand the question; the comparison explains how those are told apart.

§ 05

Parts.

Five packages, one shared vocabulary. Each is published standalone and split from a single development monorepo.

Reflection "array<K, V>" /** @param */ reader parser phpdoc typesTypeLang\Type\* printer "array"
Everything speaks the same AST. Parse a string, read a reflection, print back — or walk the nodes with a visitor.

type-lang/types

AST node classes — the shared vocabulary of the ecosystem.

composer require type-lang/types

type-lang/parser

Parses TypeLang syntax into an AST, validating the grammar. Strict or partial mode, feature toggles, readable errors.

composer require type-lang/parser

type-lang/printer

Renders nodes back to strings: the full pretty form, or a native PHP type declaration.

composer require type-lang/printer

type-lang/reader

Builds nodes from the types exposed by PHP Reflection objects.

composer require type-lang/reader

type-lang/phpdoc

Parses /** ... */ comments into a graph of description and tags.

composer require type-lang/phpdoc
// A string in, a tree out.
$parser = new TypeLang\Parser\TypeParser();
$type   = $parser->parse('array{ key: int }');

// A tree in, a string out.
echo new TypeLang\Printer\NativeTypePrinter()->print($type);  // array
echo new TypeLang\Printer\PrettyTypePrinter()->print($type);  // array{ key: int }