Skip to content

Commit 9ac5426

Browse files
authored
Reintroducing the original args sections
1 parent 08c16a2 commit 9ac5426

File tree

1 file changed

+48
-9
lines changed

1 file changed

+48
-9
lines changed

docs/ember/components.md

Lines changed: 48 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -126,19 +126,21 @@ export default class ArgsDisplay extends Component<ArgsDisplaySignature> {
126126
{{/each}}
127127
</ul>
128128
```
129+
129130
### Understanding `args`
130131
131-
Looking at that example above, Typescript knows what types `this.args` has, but how? In the `constructor` version, we explicitly _named_ the type of the `args` argument. Here, it seems to just work automatically. This works because the type definition for a Glimmer component looks roughly like this:
132+
Now, looking at that bit of code, you might be wondering how it knows what the type of `this.args` is. In the `constructor` version, we explicitly _named_ the type of the `args` argument. Here, it seems to just work automatically. This works because the type definition for a Glimmer component looks roughly like this:
133+
134+
```typescript
135+
export default class Component<Args extends {} = {}> {
136+
readonly args: Args;
132137

133-
```typescript
134-
export default class Component {
135-
args: Readonly<Args>;
136-
constructor(owner: unknown, args: Args);
137-
}
138-
```
138+
constructor(owner: unknown, args: Args);
139+
}
140+
```
139141
140142
{% hint style="info" %}
141-
Not sure what’s up with `<Args>` or `<S>` _at all_? We highly recommend the [TypeScript Deep Dive](https://basarat.gitbooks.io/typescript/) book’s [chapter on generics ](https://basarat.gitbooks.io/typescript/docs/types/generics.html) to be quite helpful in understanding this part.
143+
Not sure what’s up with `<Args>` _at all_? We highly recommend the [TypeScript Deep Dive](https://basarat.gitbooks.io/typescript/) book’s [chapter on generics ](https://basarat.gitbooks.io/typescript/docs/types/generics.html) to be quite helpful in understanding this part.
142144
{% endhint %}
143145
144146
The type signature for Component, with `Args extends {} = {}`, means that the component _always_ has a property named `args`
@@ -156,6 +158,44 @@ let b = ["hello", "goodbye"]; // Array<string>
156158
157159
In the case of the Component, we have the types the way we do so that you can’t accidentally define `args` as a string, or `undefined` , or whatever: it _has_ to be an object. Thus, `Component<Args extends {}>` . But we also want to make it so that you can just write `extends Component` , so that needs to have a default value. Thus, `Component<Args extends {} = {}>`.
158160
161+
### Giving `args` a type
162+
163+
Now let’s put this to use. Imagine we’re constructing a user profile component which displays the user’s name and optionally an avatar and bio. The template might look something like this:
164+
165+
```text
166+
<div class='user-profile' ...attributes>
167+
{{#if this.avatar}}
168+
<img src={{this.avatar}} class='user-profile__avatar'>
169+
{{/if}}
170+
<p class='user-profile__bio'>{{this.userInfo}}</p>
171+
</div>
172+
```
173+
174+
Then we could capture the types for the profile with an interface representing the _arguments_:
175+
176+
```typescript
177+
import Component from '@glimmer/component';
178+
import { generateUrl } from '../lib/generate-avatar';
179+
180+
interface User {
181+
name: string;
182+
avatar?: string;
183+
bio?: string;
184+
}
185+
186+
export default class UserProfile extends Component<User> {
187+
get userInfo(): string {
188+
return this.args.bio ? `${this.args.name} ${this.args.bio}` : this.args.name;
189+
}
190+
191+
get avatar(): string {
192+
return this.args.avatar ?? generateUrl();
193+
}
194+
}
195+
```
196+
197+
Assuming the default `tsconfig.json` settings \(with `strictNullChecks: true`\), this wouldn't type-check if we didn't _check_ whether the `bio` argument were set.
198+
159199
## Generic subclasses
160200
161201
If you'd like to make your _own_ component subclass-able, you need to make it generic as well.
@@ -177,4 +217,3 @@ export default class FancyInput<Args extends FancyInputArgs = FancyInputArgs> ex
177217
```
178218
179219
Requiring that `Args extends FancyInputArgs` means that subclasses can have _more_ than these args, but not _fewer_. Specifying that the `Args = FancyInputArgs` means that they _default_ to just being `FancyInputArgs`, so users don't need to supply an explicit generic type parameter here unless they're adding more arguments to the class.
180-

0 commit comments

Comments
 (0)