A component that reads PAD's data - the props of an island, the JSON of a page - knows its
shape only from what the PHP happens to make. pad types writes that shape down as
TypeScript, made from the data itself:
pad types shop orders # to standard output
pad types shop orders --out=www/shop/src/types/pad.d.ts
OrdersVars - the variables of the page's PHP, read from its sample
(_samples/orders.json, see Samples); a page without a sample gets one
captured first.OrdersAnswer - the JSON the page answers with padFormat=json, what its
$padExpose names (Data answers), when it answers one.unknown[], a value that was null is
null - capture the page with data that shows every field.How a value becomes a type:
|
PHP fragments/typescript_types_1.php |
HTML fragments/typescript_types_1.pad |
Result |
|---|---|---|
|
|
export interface OrdersVars {
orders: {
id: number;
total: number;
customer: {
name: string;
};
gift?: boolean;
}[];
note: null;
}
|
A list of rows is one row type - a key some rows lack is optional (gift?), a key
whose rows disagree gets a union - and other lists are a union of their items. A component then
types its props from the declarations, and tsc --noEmit fails on a field the PHP does
not have:
import type { OrdersVars } from './types/pad';
type Order = OrdersVars['orders'][number];
export default function OrderRow(order: Order) { ... }
The islands application types one island this way (examples/typed), its
npm run types and npm run check doing both steps.