}
```
**Runtime validation with assertions (using getters):**
```glimmer-js
// app/components/data-table.gjs
import Component from '@glimmer/component';
import { assert } from '@ember/debug';
class DataTable extends Component {
// Use getters so validation runs on each access and catches arg changes
get columns() {
assert(
'DataTable requires @columns argument',
this.args.columns && Array.isArray(this.args.columns),
);
assert(
'@columns must be an array of objects with "key" and "label" properties',
this.args.columns.every((col) => col.key && col.label),
);
return this.args.columns;
}
get rows() {
assert('DataTable requires @rows argument', this.args.rows && Array.isArray(this.args.rows));
return this.args.rows;
}
{{#each this.columns as |column|}}
{{column.label}}
{{/each}}
{{#each this.rows as |row|}}
{{#each this.columns as |column|}}
{{get row column.key}}
{{/each}}
{{/each}}
}
```
**Template-only component with TypeScript:**
```glimmer-ts
// app/components/icon.gts
import type { TOC } from '@ember/component/template-only';
interface IconSignature {
Args: {
name: string;
size?: 'small' | 'medium' | 'large';
};
Element: HTMLSpanElement;
}
const Icon: TOC =
;
export default Icon;
```
**Documentation with JSDoc:**
```glimmer-js
// app/components/modal.gjs
import Component from '@glimmer/component';
/**
* Modal dialog component
*
* @param {Object} args
* @param {boolean} args.isOpen - Controls modal visibility
* @param {() => void} args.onClose - Called when modal should close
* @param {string} [args.title] - Optional modal title
* @param {string} [args.size='medium'] - Modal size: 'small', 'medium', 'large'
*/
class Modal extends Component {
{{#if @isOpen}}
{{#if @title}}
{{@title}}
{{/if}}
{{yield}}
{{/if}}
}
```
Argument validation provides better error messages during development, serves as documentation, and enables better IDE support.
Reference: [TypeScript in Ember](https://guides.emberjs.com/release/typescript/)