Read the announcement: GTKX 1.0: The React framework for Linux.
This release makes GObject subclassing a first-class part of the API and rebuilds @gtkx/testing on GTK's own accessibility tree and input handling. Virtual functions are reachable by name and chainable through super, a class can adopt interfaces its parent never implemented, and property writes are checked against the ParamSpec. An application parses its command line the way a C application does, and the widgets GTK4 forbids from being parented portal themselves. Every accessible read a test makes goes through gtk_test_accessible_check_* instead of the props the React layer recorded, and userEvent.click reproduces GTK's own targeting rather than forcing widget state. The generated bindings carry full documentation from the GIR data, and api.json declares which entrypoints are public.
Breaking changes
The generated store has to be rebuilt
gtkx dev, gtkx build and gtkx codegen regenerate node_modules/.gtkx on the first run after upgrading. An rc.4 store will not run against 1.0: the generated modules import runtime symbols that do not exist at rc.4, and the vtable and callback descriptors changed. A project with codegen: false needs a store built by 1.0.
Virtual method overrides are named with a vfunc prefix
A subclass no longer fills a C vtable slot by overriding the plain method name. Every slot is keyed vfunc plus the PascalCased vtable field, and the generated wrapper classes declare those members, so super.vfuncMeasure(...) chains up. Code keeping the old spelling silently stops overriding anything.
// Before
class ReturningModel extends Gtk.StringList {
override getNItems(): number {
return 1;
}
}
// After
class ReturningModel extends Gtk.StringList {
override vfuncGetNItems(): number {
return 1;
}
}Since the override no longer shadows the generated binding, model.getItem(0) reaches it through the vtable and the rc.4 prototype.getItem.call(...) workaround is gone. A class field holding a function never reaches the vtable, because it is assigned per instance after registration. vfuncDispose, vfuncFinalize, vfuncGetProperty and vfuncSetProperty get no typed member, but declaring them still works.
runApplication takes an argv, and applications come from createApplication
runApplication(application, argv) returns { isPrimary, exitStatus }. Rather than registering and activating itself, it hands the argv to GLib's local command line handling, so the application's own options are parsed, --help prints, and a second instance forwards its command line to the process owning the application ID. It throws when handed an application GTKX did not derive, because GLib parses a given application's command line at most once; createApplication(base, props) builds one.
// Before
const application = new Gtk.Application({ applicationId: "org.example.App" });
runApplication(application);
// After
const application = createApplication(Gtk.Application, { applicationId: "org.example.App" });
const { exitStatus } = runApplication(application, ["App", ...process.argv.slice(2)]);
process.exitCode = exitStatus;Applications rendered as <GtkApplication> or <AdwApplication> are carried over. gtkx dev forwards everything after -- to the application. An unrecognized option is now rejected by GApplication instead of ignored, and post-activate props such as menubar apply only when activation happens.
Windows, applications, dialogs and size groups portal themselves
GtkWindow and its subclasses, GtkApplication, GtkSizeGroup and the Adwaita dialogs mount at the top level wherever they sit in JSX, so the rc.4 pattern of writing createPortal(..., rootElement) by hand is gone. Two behavior changes come with it: transientFor defaults to the nearest enclosing window when the prop is undefined (pass null to keep a window free-standing), and GtkApplicationWindow portals into the application useApplication returns, throwing when there is no <GtkApplication> ancestor.
A child no behavior claims throws instead of being dropped
The reconciler used to ignore a child left in the default slot that no attach behavior claimed. It now throws, naming the child type, the parent type and the three remedies: pass it to the prop that takes it, portal it to rootElement, or register an attach behavior with defineElements.
// Before: the label was silently dropped
<GtkPaned>
<GtkLabel>Start</GtkLabel>
</GtkPaned>
// After
<GtkPaned startChild={<GtkLabel>Start</GtkLabel>} />This is a runtime error, not a compile error: every widget's generated props declare children, so the old tree still type-checks.
Deprecated containers lost their child behaviors
AdwLeaflet, AdwSqueezer, AdwPreferencesWindow and GtkComboBox no longer take children, and AdwFlap no longer takes content, so children written under any of them hit the unclaimed-child error. Migrate to AdwNavigationSplitView or AdwNavigationView, AdwBreakpointBin or AdwMultiLayoutView, AdwPreferencesDialog, and AdwOverlaySplitView. AdwFlapProps.content and GtkComboBoxProps.child are settable instead. AdwClampScrollable's child must implement Gtk.Scrollable, and AdwExpanderRow dropped its deprecated actions slot in favor of suffix.
AdwAlertDialog children fill the extra child
Children now go through adw_alert_dialog_set_extra_child and land below the heading and above the response buttons, where they used to replace the dialog's whole content. The extraChild prop is gone.
// Before
<AdwAlertDialog responses={responses} extraChild={<InteractiveFields />} />
// After
<AdwAlertDialog responses={responses}>
<InteractiveFields />
</AdwAlertDialog>ElementBehavior loses mount and unmount, and gains constructOnly
The two node-level hooks are gone with no direct replacement; the nearest substitute is flush(object, context), which runs after every commit touching the node. In their place, constructOnly?: string[] names props a behavior can apply only while the element is being built. The list helper sets it for any list prop declared with neither a remove nor a clear hook, which covers GtkAboutDialog.creditSections and GtkApplication.mainOptions: changing either after a non-empty value has been applied now throws.
@gtkx/testing reads accessibility from GTK
Every accessible read goes through gtk_test_accessible_check_state, check_property and check_relation instead of the props the React layer recorded. A widget GTK publishes no attribute for makes the matcher throw rather than falling back to a getter; a widget GTK does publish one for answers even when nothing declared it in JSX. What this changes in existing suites:
- Accessible names follow WAI-ARIA naming, so a name-prohibited role computes no name and a
GtkFrame's label no longer names it forgetByRole. UsegetByLabelText. - Mnemonic markers are stripped from any widget whose
getUseUnderline()is true, so{ name: "_OK" }becomes{ name: "OK" }. - Numeric values are compared within 0.001, and GTK reports the reachable maximum, so a scrollbar's
maxis its upper bound less one page. - A
MIXEDpressed tristate matches neitherpressed: truenorpressed: false. Assert it withtoBePartiallyPressed. - An
AdwSwitchRowpublishesSWITCHon the row as well as its innerGtk.Switch, so a role query needs{ as: Gtk.Switch }to disambiguate.
Three matchers were removed and one renamed:
// Before
expect(expander).toBeExpanded();
expect(entry).toHavePlaceholderText("Search");
expect(box).toBeEmpty();
// After
expect(expander).toHaveAccessibleState(Gtk.AccessibleState.EXPANDED, true);
expect(entry).toHaveAccessibleProperty(Gtk.AccessibleProperty.PLACEHOLDER, "Search");
expect(box).toBeEmptyWidget();toBeSelected moved to toHaveAccessibleState the same way. Matchers are registered by name, so a call to a removed one fails at assertion time in a loosely typed suite. On the reader side, getWidgetNodeText is now getWidgetText, and getWidgetTextContent, getWidgetInvalidState and getWidgetErrorMessage left the entrypoint in favor of toHaveTextContent, toBeInvalid and toHaveAccessibleErrorMessage.
Queries only see mapped widgets
The tree walk backing every query, getRoles, logRoles and the tree dump now filters on widget.getMapped(). A widget rendered with visible={false} is not findable and { hidden: true } does not bring it back, a widget on a non-visible Gtk.Stack page is invisible until that page shows, and a closed popover's contents (including a Gtk.DropDown's popup list) are not findable until it pops up. Capture such widgets through a ref, or make them visible first.
userEvent.click follows GTK's own targeting
click used to special-case Gtk.Button, force setActive on a Gtk.Switch, then fall back to a synthesized gesture at the nearest clickable ancestor's center. It now walks outwards from the clicked widget, keeps every widget carrying a primary-button click gesture with a tracked listener, and stops at the first widget that claims the press. Presses are delivered at coordinates derived from the clicked widget's bounds, so a container's gesture reads the child's position.
So clicking a label inside a row targets the row, onPressed on ancestor boxes fires for clicks on descendants, and no gesture is ever synthesized on a widget that has none. Where GTK4 implements a click in C on its own gesture, the outcome is applied through the public action GTK's handler invokes:
- A
Gtk.ListView,Gtk.GridVieworGtk.ColumnViewrow grabs focus, replaces the selection throughlistitem.select, and activates only on the second press or when the view setssingle-click-activate. A single click no longer fires the view'sactivatesignal, where rc.4 fired it on every click and never moved the selection. SetsingleClickActivateor usedblClick. - A
Gtk.TreeExpandertoggles its row throughlistitem.toggle-expand; a click on its child label falls through to the enclosing row. - A
GtkColumnViewTitlesorts throughGtk.ColumnView.sortByColumn, ascending first and inverted while it is already the primary sort column. - Column-view cells and the header row are click-transparent: the press reaches the row or view behind them.
Two neighbors changed with it. clear now focuses the widget and deletes through deleteText/deleteInteractive, so delete-text and delete-range handlers run, and it throws for a non-editable widget or a refused deletion. selectOptions and deselectOptions are duck-typed against the container's index and select methods instead of branching on concrete classes, so Gtk.FlowBox and a non-DropDown Adw.ComboRow work, selecting a row no longer calls row.activate(), and Gtk.ComboBox is no longer supported.
The screenshot surface collapsed to screenshot
captureAndSaveScreenshot, logScreenshotPath and WindowSelector are gone. screen.screenshot went from (selector?, options?) to (options?) and always captures the active mapped toplevel. Writing to disk is opt-in through the new path option; nothing is written to a temporary file.
// Before
await screen.screenshot(0, { scale: 2 });
// After
await screen.screenshot({ scale: 2, path: "out/window.png" });Collection selection and expansion are fully controlled
selectedIds and expandedIds used to be applied only when present. Both are now always applied, so a view without the prop is driven back to nothing selected and every row collapsed, and the app must feed the reported ids back. They are also re-asserted when the widget drifts, so a click on a row absent from selectedIds is snapped back.
const [selectedIds, setSelectedIds] = useState<string[]>([]);
<ListView items={items} renderItem={renderItem} selectedIds={selectedIds} onSelectionChanged={setSelectedIds} />ListItem.hideExpander, indentForDepth and indentForIcon are now shouldHideExpander, shouldIndentForDepth and shouldIndentForIcon; an item literal using the old names loses the setting. ColumnViewProps omits rowFactory, because ColumnView installs its own to drive rowProps. DropDown and ComboRow build a flat collection, so ListItem.children is ignored. The objects inside a collection model no longer carry the item id either, so code reading ids off listView.getModel() reads empty strings.
registerClass validates property writes
A property declared through registerClass({ properties }) now gets a checked setter on all three of its spellings, unless the class defines the camelCase member itself. A property without WRITABLE always throws a TypeError, and a CONSTRUCT_ONLY one throws unless it is set through the constructor. A writable property is checked by a per-property type guard and then by g_param_value_validate, and a value GObject would have corrected throws a RangeError unless the ParamSpec is marked LAX_VALIDATION. A refused write leaves the stored value untouched and emits no notify.
probe.red = 9999;
// Before: stored 9999, and probe.red served 9999 back
// After: RangeError: Probe.red: cannot set property 'red' to 9999; the value is
// invalid or out of range for type 'gint'At rc.4 the accessor stored whatever it was handed, so a read-only property behaved as writable and an out-of-range value survived until something tried to marshal it. Define the camelCase member on the class to take ownership of the property and turn the checks off. A JSX prop landing on such a property goes through the same setter, so a value the ParamSpec refuses aborts the render instead of being stored.
Registration also rejects a ParamSpec whose name is not its key's canonical spelling, since the ParamSpec's own name is what GObject emits notify with: write paramSpecInt("dew-point", ...) under the key dewPoint, not paramSpecInt("dewPoint", ...).
@gtkx/runtime removals and signature changes
tryGetHandle was deleted and the setWrapper re-export dropped, so a wrapper carrying no handle throws instead of marshalling as null. newObjectWithProperties(gtype, props) is now newObjectWithProperties(gtype, props, wrapper) with plain values rather than [descriptor, value] pairs; descriptors come from the new registerConstructProperties(cls, bindings). A constructor key with no declared binding is resolved against the type's ParamSpec and validated before GObject sees it, so new Gtk.Label({ "accessible-role": 9999 }) now throws rather than emitting a GLib critical. registerInterface takes an InterfaceLayout ({ vfuncs, properties }), and callback descriptors need hasUserData and gained destroyKind.
getInstanceType now reads the GType off the instance's native handle rather than off its wrapper class, so a row inside a Gtk.ListView reports GtkListItemWidget rather than GtkWidget. The old answer is getClassType(cls), newly exported alongside the AnyClass type.
Generated class constructors no longer destructure their props and the root constructor takes object rather than Record<string, unknown>, so a subclass declaring constructor(props: Record<string, unknown>) must widen it. A callable is dropped from the bindings when it cannot be called correctly, which covers Gio.Cancellable.prototype.cancellableConnect, Gtk.CClosureExpression.new and GObject.SignalGroup.prototype.connectData among others. Codegen emits all of this, so only a hand-written descriptor needs editing.
Smaller breaking changes
DEFAULT_USER_EVENT_SIGNALSno longer coversGtkAppChooserButton,GtkAppChooserWidget,GtkComboBox,GtkIconView,GtkTreeSelectionorGtkTreeView, so handlers on those signals also fire for changes GTKX writes during a commit. Restore them throughuserEventSignalsingtkx.config.ts.- The MCP reference tools gained an optional
projectRoot, and now try the project containing the working directory before a connected app's root, inverting the rc.4 order.
New features
registerClass adopts interfaces, and vtable slots are callable
RegisterClassOptions.implements lists interfaces the new type implements on top of the ones it inherits. Their slots are filled from the class's vfunc-prefixed members and checked against the interface's generated Impl type, an interface listed before its prerequisite still registers, adopted properties answer g_object_get and g_object_set, and a slot the class does not fill keeps the interface's own default. rc.4 rejected any interface the parent did not already conform to.
class Sectioned extends GObject implements Gtk.SectionModelImpl {
vfuncGetNItems(): number {
return items.length;
}
// ...
}
registerClass(Sectioned, { typeName: "GtkxSectionStore", implements: [Gio.ListModel, Gtk.SectionModel] });callVfunc(owner, key, instance, inputs) and callParent(klass, methodName, instance, ...inputs) are public. callVfunc is what the generated members call; callParent chains up exactly one level and reaches class slots, construct-time slots and interface slots alike, including the four with no generated member. The rc.4 rejection of constructed, setProperty and getProperty is gone: vfuncConstructed runs with the wrapper already bound, so getHandle(this) works inside it, and it runs for instances GTK or Gtk.Builder creates, where the subclass constructor never does.
registerClass returns the registered class as RegisteredClass<T, TProperties>, whose instances carry a type-level map of the installed property names in camelCase. useProperty reads its allowed names off that map, so a hand-written subclass's own properties are addressable for the first time. Bind the call to a name rather than calling it as a bare statement, and leave the properties object to inference.
const Swatch = registerClass(SwatchBase, {
typeName: "ExampleSwatch",
properties: { red: paramSpecInt("red", null, null, 0, 255, 0, ParamFlags.READWRITE) },
});
const red = useProperty(swatch, "red"); // number | undefinedcreateElementComponent is part of @gtkx/react/config
The factory the generated @gtkx/jsx store builds its elements with is now public, so a class registerClass created, which codegen cannot emit an element for, can still be rendered. The element inherits the props, signal handlers, defaults and behaviors registered for each of the class's ancestors, and the component routes a prop whose value is an element into that prop's slot. Name the props as the type argument, since the GType name says nothing about them.
const SwatchElement = createElementComponent<SwatchProps>("ExampleSwatch");
<SwatchElement red={200} widthRequest={48} />;A JavaScript function is accepted wherever a GObject.Closure is expected
toClosure, tryToClosure, ClosureCallback and ClosureMarshalError are new exports, and the seventeen registry functions that build a closure on the caller's behalf take GObject.Closure | ClosureCallback.
source.bindPropertyFull("value", target, "value", flags, (value) => value * 2, (value) => value / 2);disconnectSignal and connection tracking
connectSignal records every handler id it creates, and the new disconnectSignal(instance, handlerId) disconnects through that record. GObject.prototype.disconnect is built on it, and onceSignal and offSignal untrack as well, so a disconnected handler is never reported as still listening. Detailed names such as notify::label match their base name.
Generated bindings are fully documented
Generated declarations now render @param, @returns, @throws, @deprecated and @since from the GIR data: the Gtk store alone carries 4407 @param and 1558 @deprecated tags. DocBook markup becomes Markdown and #Type::signal references render as links. The JSX store is documented too, down to each onNotify<Prop> handler. A project with @typescript-eslint/no-deprecated enabled should expect new lint failures after regenerating.
Worker chunks in gtkx build
gtkx build now recognizes new URL("./relative", import.meta.url) written directly inside a new Worker(...) call, emits the target as its own chunk under dist/workers/, and rewrites the URL. Repeated references to the same module share one chunk. Hoisting the URL into a variable fails the build with a message naming the binding.
New Adwaita elements
AdwSidebar takes AdwSidebarSection children, which take AdwSidebarItem children. AdwMultiLayoutView takes its layouts through a layouts prop holding AdwLayout elements, and fills each Adw.LayoutSlot through a prop named after its id plus a Slot suffix.
<AdwMultiLayoutView
layoutName="wide"
layouts={<AdwLayout name="wide">{/* ... <AdwLayoutSlot id="sidebar" /> ... */}</AdwLayout>}
sidebarSlot={<GtkLabel>Side</GtkLabel>}
/>New testing matchers and extension points
toHaveAccessibleState(state, expected?) and toHaveAccessibleProperty(property, expected?) assert any attribute GTK publishes, with overloads pairing each one with the value type it carries. toAppearBefore and toAppearAfter compare two widgets by position in a depth-first walk, and the toContainAnyBy* and toContainOneBy* families run a built-in query against a widget's own subtree.
expect(toggle).toHaveAccessibleState(Gtk.AccessibleState.PRESSED, Gtk.AccessibleTristate.MIXED);
expect(form).toContainOneByLabelText("Email");Testing Library's extension points came with them: buildQueries, getElementError, queryAllByObjectProperty, queryHelpers, computeHeadingLevel, prettyFormat, getQueriesForElement (an alias of within), and createEvent, which records a WidgetEvent without emitting it.
userEvent.setup and application accelerators
userEvent.setup(options?) returns an instance whose helpers share one keyboard and pointer state, so held modifiers carry across that instance's calls but not across instances, and honors a delay after each helper resolves. The module-level userEvent keeps its own shared state. userEvent.keyboard now tries application accelerators first, so a combination bound with setAccelsForAction fires its action in tests.
api.json declares the public API surface
A new api.json lists the fourteen entrypoints GTKX supports importing: @gtkx/cli/env, @gtkx/cli/vitest-plugin, @gtkx/codegen, @gtkx/components, @gtkx/components/adw, @gtkx/config, @gtkx/config/vite-plugin, @gtkx/css, @gtkx/gl, @gtkx/react, @gtkx/react/config, @gtkx/runtime, @gtkx/testing and @gtkx/vitest. Anything else a package happens to export is internal by declaration and can change without a major version. The published API reference is generated from the same list, so it now covers @gtkx/cli, @gtkx/codegen, @gtkx/components/adw, @gtkx/config/vite-plugin and @gtkx/react/config. ConfigLoader and ModuleExport moved onto the public surface alongside it.
Smaller additions
rowPropsonColumnViewresolvesListRowPropsper row, which is the only way to reach aGtk.ColumnViewRowsince it is not a widget.ListViewandColumnViewboth acceptexpanderDescriptions.mainOptionsonGtkApplicationregistersMainOptionrecords throughaddMainOptionbefore the command line is parsed, reachable fromonHandleLocalOptions.gtkx_get_widget_propsreturns named properties as{ type, value }. The subtree the MCP tools return is now bounded, filled breadth first under amaxDepth(default 8) and 30 widgets in all, withhiddenChildrenreporting what was cut so an agent can drill in with a second call.gtkx_query_widgetswidenedby: "name"to name, accessible label and rendered text.- Opening a render root connects it to React DevTools when the browser extension's hook is present. An update triggered from a GTK signal handler now commits once the emission unwinds rather than in the middle of it.
GValuemarshalling covers thegchar,guchar,glongandgulongfundamentals, which used to fall through to an unsupported-type error.- Accessible props apply to anything implementing
Gtk.Accessiblerather than only to widgets, and the relation props widened to match. - The generated OpenGL bindings carry the C prototype, the providing feature, aliases and the GLX opcode; core-profile selection applies require and remove blocks in registry order.
create-gtkxwrites a build allowance for the chosen package manager, dev-depends on@gtkx/mcp, and explains a failed dependency install with the exact commands that recover it.- New guides cover subclassing GObject, worker threads, and the reworked testing surface.
Performance
- Controlled expansion and selection stopped walking every row. Visible order and positions come from the JavaScript index, so expanding one parent in a 5001-row tree costs one
getRowand onesetExpanded, and moving the selection costs none. Rows are materialized lazily. Because they are addressed positionally, a pure reorder ofitemsemits noitems-changedat all, which anything connected tolistView.getModel()will see. - A validated property write costs one GValue fill and one
g_param_value_validate, roughly half a microsecond per changed write. Reads and writes of the value already stored are unaffected, since the equality short-circuit runs first. - A faster call path for plain function bindings. A binding whose arguments are all pass-throughs skips building per-argument values, the out-parameter scan and tuple packing on every call, and out-parameter plans are precomputed once instead of filtered per call. Every generated getter, setter and simple method benefits.
Bug fixes
- Fixed rows in a collection being identified by
ListItem.id, so two items sharing an id rendered the same value and expanded together. Rows are addressed per occurrence now. - Fixed
DropDownandComboRowechoing a programmaticselectedIdback throughonSelectionChanged; both report user choices only. - Fixed
accessibleExpanded,accessibleSelectedandaccessibleVisitedfailing with an FFI error, and accessible props being dropped when GTK overwrote them itself. - Fixed
notifycarrying the key a property was registered under rather than theParamSpec's canonical name, so nonotify::connection could match it. - Fixed a property set through
g_object_set_propertyemittingnotifytwice, which ran everynotify::handler and ReactonNotifyXprop twice for writes reaching a custom property from the GObject side. - Fixed a
GValuetyped as an interface failing to resolve a setter or getter, so a property or signal argument typedGio.ListModelround-trips. - Fixed a property whose stored value does not fit its type surfacing an opaque marshalling error from bindings, expressions and sorters. Reads check the value against the
ParamSpecfirst and throw aTypeErrornaming the property and the type it holds. - Fixed the dashed and underscored spellings of a property getting their own storage when the class defined the camelCase member itself.
- Fixed the wrapper for a
registerClassinstance keeping its GObject alive forever. Reference counts now match those of unregistered parents. - Fixed chaining up from a
vfuncMeasureoverride handing the parent implementation zeroed out baselines instead of GTK's -1, so a forwarding override reports what the parent reports. - Fixed arrays of inline structs whose length arrives in a separate out parameter being read at the wrong stride, so
Gdk.Display.mapKeyvalandPango.Layout.getLogAttrsreturn usable records. Out and inout descriptors no longer ignore the extra pointer indirection. - Fixed
Root.unmountleaving aGtk.Applicationregistered, so the same application id can be registered again. - Fixed
userEvent.scrolljumping straight to the target value, which left virtualized views anchored on rows that were no longer shown. - Fixed
screenshotleaving out mapped popovers, which render on their own surfaces. - Fixed placeholder, display value and selection reads being gated on concrete GTK classes, so a
Gtk.TextView, aGtk.PasswordEntry, a selectableGtk.Labeland anAdw.ComboRownow answer their queries. - Fixed assertions made immediately after
await render(...)missing accessibility state the just-committed tree published. - Fixed
gtkx_clickacting on the enclosing list row instead of theGtk.TreeExpanderunder the pointer; every MCP target goes throughuserEvent.clicknow. - Fixed the MCP server deleting a socket another server still owns, so two servers starting at once end with one owner and one refusal. A leftover socket is removed only after a conclusive probe, where any connect error used to be read as proof of a dead server.
- Fixed a scaffolded project's
testscript sitting in watch mode, emitting toout-tsc, and never type-checking its tests. - Fixed
gtkx devidling forever when the application refused its command line, and leaking a custom--conditionsinto the application process. - Fixed
gtkx build --asset-baseemittingrequire("path")calls an ESM bundle cannot evaluate. - Fixed
glib-compile-schemasandglib-compile-resourcesresolution, where a non-executable file on PATH used to win. - Fixed interrupted Vitest runs leaving orphaned
weston,swayanddbus-daemonprocesses behind.@gtkx/vitestalso no longer injects a setup file, so a project's owntest.setupFilesare left alone. - Fixed codegen emitting a store that would not type-check when two configured namespaces produce the same generated type name.