Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

1.0 Docs Updates #562

Merged
merged 7 commits into from
Apr 26, 2023
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ TypeScript-powered tooling for Glimmer templates.

[Glint] is a set of tools to aid in developing code that uses the Glimmer VM for rendering, such as [Ember.js] v3.24+ and [GlimmerX] projects. Similar to [Vetur] for Vue projects or [Svelte Language Tools], Glint consists of a CLI and a language server to provide feedback and enforce correctness both locally during editing and project-wide in CI.

⚠️ Note: **Glint is still under active development!** Please bear with us and expect breaking changes and rough edges as we work toward a stable release.

[glint]: https://typed-ember.gitbook.io/glint
[ember.js]: https://www.emberjs.com
[glimmerx]: https://github.com/glimmerjs/glimmer-experimental
Expand Down
17 changes: 11 additions & 6 deletions docs/contents.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,13 @@
## Using Glint

* [Configuration](configuration/\_index.md)
* [Project References](configuration/project-references.md)
* [Glint Types](glint-types.md)
* [`@glint` Directives](directives.md)
* [Glint with JavaScript](with-js.md)
* [Project References](configuration/project-references.md)

## Environments

* [Ember](using-glint/ember/README.md)
* [Installation](ember/installation.md)
* [Component Signatures](ember/component-signatures.md)
Expand All @@ -21,9 +27,8 @@
* [Installation](glimmerx/installation.md)
* [Component Signatures](glimmerx/component-signatures.md)
* [Template Components](glimmerx/template-components.md)
* [Glint with JavaScript](with-js.md)
* [@glint Directives](directives.md)
* [Glint Types](glint-types.md)
* [Migrating](migrating.md)
* [Diagnosing Common Error Messages](diagnosing-common-error-messages.md)

## Troubleshooting
* [Migration Notes](migrating.md)
* [Common Error Messages](diagnosing-common-error-messages.md)
* [Known Limitations](known-limitations.md)
16 changes: 16 additions & 0 deletions docs/diagnosing-common-error-messages.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,22 @@ declare module '@glint/environment-ember-loose/registry' {
}
```

## Invalid module name in augmentation

```
Invalid module name in augmentation: module '@glint/environment-ember-loose/registry' cannot be found.`
```

TypeScript will only allow you to add declarations for a module if it's already seen the original. In other words,
if you've never directly or transitively imported `@glint/environment-ember-loose/registry` anywhere in your project
that TypeScript can see then it won't allow you to add a registry entry.

To fix this, [add `import '@glint/environment-ember-loose'` somewhere in your project][env-import]. This will ensure that the
registry, as well as other important type information like template-aware declarations, are visible to vanilla
`tsc` and `tsserver`.

[env-import]: ./ember/installation.md

## Does not satisfy the constraint 'Invokable<AnyFunction>'

```
Expand Down
13 changes: 12 additions & 1 deletion docs/directives.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ Glint's behavior. Additional comment text can follow directives to document
their purpose. These directives correspond to the similarly-named directives
in TypeScript.

`@glint` directives may _only_ be applied in template comments, not in
TypeScript outside of templates.

## `@glint-expect-error`

The `@glint-expect-error` directive operates similarly to `@glint-ignore` in
Expand Down Expand Up @@ -48,11 +51,19 @@ migration process.
Example:

```hbs
{{! @glint-nocheck: this whole teplate needs work }}
{{! @glint-nocheck: this whole template needs work }}

<MyComponent @stringArg={{123}} />

<AnotherComponent @badArg='foo' />

{{two-arg-helper 'bar'}}
```

**Note**: the [`auto-glint-nocheck`] script in the `@glint/scripts` package
can automate the process of adding `@glint-nocheck` directives at the top
of every template with type errors in your project. This allows you to adopt
Glint in a project immediately for all new templates while incrementally
migrating your existing ones to make them typesafe over time.

[`auto-glint-nocheck`]: https://github.com/typed-ember/glint/tree/main/packages/scripts#auto-glint-nocheck
6 changes: 0 additions & 6 deletions docs/ember/authoring-addons.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,12 +92,6 @@ export default interface AwesomeAddonRegistry {

By defining the component, helper, and modifier types in separate importable files (rather than just directly in `template-registry.d.ts`), consumers using [first class component templates] can import them from the correct paths.

## Stability Note

{% hint style="warning" %}
Note: **Glint is still under active development!** Please bear with us and expect breaking changes and rough edges as we work toward a stable release. This could also affect the users of your addon, so you might want to see your addon's Glint support as experimental for now!
{% endhint %}

[strict mode]: http://emberjs.github.io/rfcs/0496-handlebars-strict-mode.html
[first class component templates]: http://emberjs.github.io/rfcs/0779-first-class-component-templates.html
[template registry]: template-registry.md
Expand Down
17 changes: 15 additions & 2 deletions docs/ember/installation.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
To use Glint with [Ember](https://github.com/emberjs/ember.js) v3.24 or higher, you'll add the `@glint/core`, `@glint/template` and `@glint/environment-ember-loose` packages to your project's `devDependencies`, then add a `"glint"` key to your project's `tsconfig.json`.
To use Glint with [Ember](https://github.com/emberjs/ember.js) v3.24 or higher, you'll need to:
1. add the `@glint/core`, `@glint/template` and `@glint/environment-ember-loose` packages to your project's `devDependencies`
2. add a `"glint"` key with appropriate config to your project's `tsconfig.json`
3. add `import '@glint/environment-ember-loose';` somewhere in your project

Read on for a more detailed explanation of each of these steps.

{% tabs %}
{% tab title="Yarn" %}
Expand Down Expand Up @@ -33,9 +38,17 @@ If you are using `ember-template-imports` in your project, also install the `@gl

Note that, by default, Glint will assume you want it to analyze all templates in the codebase that are covered by your `tsconfig.json`. To ignore any type errors up front so that you can incrementally migrate your project to typesafe templates, consider using [the `auto-glint-nocheck` script](https://github.com/typed-ember/glint/tree/main/packages/scripts#auto-glint-nocheck) to add [`@glint-nocheck` comments](../directives.md#glint-nocheck) to your existing templates that would produce errors.

Finally, ensure you've added the following statement somewhere in your project's source files or ambient type declarations:

```typescript
import '@glint/environment-ember-loose';
```

You may also choose to disable TypeScript's "unused symbol" warnings in your editor, since Glint will flag any symbols that are actually unused, while `tsserver` won't understand any symbol usage that only occurs in templates.

{% hint style="info" %}

To minimize spurious errors when typechecking with vanilla `tsc` or your editor's TypeScript integration, you should add `import '@glint/environment-ember-loose';` somewhere in your project's source or type declarations. You may also choose to disable TypeScript's "unused symbol" warnings in your editor, since `tsserver` won't understand that templates actually are using them.
When typechecking with vanilla `tsc` or your editor's `tsserver` integration, adding this side-effect `import` statement ensures that TypeScript is aware of the Glint-specific types provided by the environment package. Without this line, you may find that vanilla TypeScript produces spurious errors.

{% endhint %}

Expand Down
94 changes: 94 additions & 0 deletions docs/glint-types.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,97 @@ interface MyComponentSignature {
```

Where `WithBoundArgs` accepts the names of the pre-bound arguments, `WithBoundPositionals` accepts the number of positional arguments that are pre-bound, since binding a positional argument with `{{component}}`/`{{modifier}}`/`{{helper}}` sets that argument in a way that downstream users can't override.

## Advanced Types Usage

From Glint's perspective, what _makes_ a value usable as a component is being typed as a constructor
for a value type that matches the instance type of `ComponentLike`. The same is true of helpers with
`HelperLike` and modifiers with `ModifierLike`.

While this may seem like a negligible detail, making use of this fact can allow authors with a good
handle on TypeScript's type system to pull of some very flexible "tricks" when working with Glint.
dfreeman marked this conversation as resolved.
Show resolved Hide resolved

### Custom Glint Entities

Ember (and the underlying Glimmer VM) has a notion of _managers_ that allow authors to define custom
values that act as components, helpers or modifiers when used in a template. Glint can't know how
these custom entities will work, but by using `ComponentLike`/`HelperLike`/`ModifierLike`, you can
explain to the typechecker how they function in a template.

For example, if you had a custom DOM-less "fetcher component" base class, you could use TypeScript
[declaration merging](https://www.typescriptlang.org/docs/handbook/declaration-merging.html) to
tell Glint that its instance type extended `InstanceType<ComponentLike<S>>`, where `S` is an
appropriate component signature based on how your custom component works.

```typescript
// Define the custom component base class
class FetcherComponent<Params, Payload> {
// ...
}

// Set its manager and, if necessary, template
setComponentManager(/*...*/, FetcherComponent);
setComponentTemplate(/*...*/, FetcherComponent);

// Use declaration merging to declare that the base class acts, from Glint's perspective,
// like a component with the given signature when used in a template.
interface FetcherComponent<Params, Payload> extends InstanceType<
ComponentLike<{
Args: { params: Params };
Blocks: {
loading: [];
error: [message: string];
ready: [payload: Payload];
};
}
>> {}
```

This is a fairly contrived example, and in most circumstances it would be simpler to use a standard
base class like `@glimmer/component`, but nevertheless the option exists.

**Note**: this declaration merging technique using `InstanceType<ComponentLike<...>>` is _exactly_
how Glint's own 1st-party environment packages like `@glint/environment-ember-loose` set up the
template-aware types for `@glimmer/component`, `@ember/component/helper`, etc.

### Type Parameters

When defining a class-based component, modifier or helper, you have a natural place to introduce
any type parameters you may need. For example:

```typescript
export interface MyEachSignature<T> {
Args: { items: Array<T> };
Blocks: {
default: [item: T, index: number];
};
}

export class MyEach<T> extends Component<MyEachSignature<T>> {
// ...
}
```

However, if you aren't working with a concrete base type and can only say that your value is,
for instance, some kind of `ComponentLike`, then TypeScript no longer offers you a place to
introduce a type parameter into scope:

```typescript
// 💥 Syntax error
declare const MyEach<T>: ComponentLike<MyEachSignature<T>>;

// 💥 Cannot find name 'T'. ts(2304)
declare const MyEach: ComponentLike<MyEachSignature<T>>;
```

Since what matters is the _instance_ type, however, it is possible to define `MyEach` using just
`ComponentLike` and slightly more type machinery:

```typescript
declare const MyEach: abstract new <T>() => InstanceType<
ComponentLike<MyEachSignature<T>>
>;
```

This shouldn't be a tool you frequently find the need to reach for, but it can be useful on
occasion when working with complex declarations.
2 changes: 0 additions & 2 deletions docs/known-limitations.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
**Glint is not yet stable** and is still under active development. As such, there are currently several known limitations to be aware of.

### Ember-Specific

Glint is not currently integrated with `ember-cli-typescript`, so typechecking performed during an `ember-cli` build will not take templates into account.
Expand Down
71 changes: 63 additions & 8 deletions docs/migrating.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,6 @@

## Glint 0.9.x to 1.0

{% hint style="warning" %}

Glint 1.0 is currently in a beta period. We encourage you to try out the beta and report any
issues you run into. While we don't anticipate landing any further breaking changes during the beta
cycle, be aware that it's still possible we'll do so in response to bugs or other early feedback.

{% endhint %}

Most of the changes in Glint 1.0 should appear as bugfixes and improvements to the majority of
users migrating from 0.9.x.

Expand All @@ -36,6 +28,69 @@ alongside `@glint/core` and your environment package(s).
Note also that if you publish an addon that depends on types from `@glint/template`, that addon
should likewise declare a `peerDependency` on `@glint/template` and **not** a regular `dependency`.

### `{{component}}` Typing

In `@glint/environment-ember-loose`, if you used the `{{component}}` helper to expose a "contextual
component" to your consumers without binding any additional arguments, e.g.:

```handlebars
{{yield (hash Child=(component "some-child-component"))}}
```

In 0.9.x, Glint would allow you to type that yielded component as something like:

```typescript
export interface MyComponentSignature {
Blocks: {
default: [{ Child: typeof SomeChildComponent }];
};
}
```

However, this was never quite correct: when you use the `{{component}}` helper, the value it returns
is not the actual component class itself. If `SomeChildComponent` had static members, for instance,
then according to `Child: typeof SomeChildComponent`, consumers should be able to access those
properties from the yielded `Child` value, but they wouldn't be there in the value returned from
`{{component}}`.

The only thing you are guaranteed to be able to do with the result of the `{{component}}` helper is
invoke it as a component in a template.

Accordingly, in Glint 1.0 the above combination will no longer typecheck. To fix the situation, you
can either update the signature to match the template:

```typescript
export interface MyComponentSignature {
Blocks: {
default: [{ Child: ComponentLike<SomeChildComponentSignature> }];
};
}
```

Or update the template to match the signature:


{% tabs %}
{% tab title="Template" %}

```handlebars
{{yield (hash Child=this.SomeChildComponent)}}
```

{% endtab %}
{% tab title="Backing Class" %}

```typescript
import SomeChildComponent from './some-child-component';

export default class MyComponent /* ... */ {
SomeChildComponent = SomeChildComponent;
}
```

{% endtab %}
{% endtabs %}

### `include`/`exclude` Configuration

Glint 1.0 drops support for the `transform` configuration key, which is where `include` and
Expand Down
6 changes: 0 additions & 6 deletions docs/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,6 @@ The Glint language server implements the standardized [Language Server Protocol]

![Suggesting component arguments in typeahead with type information and documentation](https://user-images.githubusercontent.com/108688/111070948-3f9b2f00-84d4-11eb-9eaa-077cadf6f380.png)

## Stability Note

{% hint style="warning" %}
Note: **Glint is still under active development!** Please bear with us and expect breaking changes and rough edges as we work toward a stable release. Also note that Glint is currently only compatible with TypeScript projects, but our aim is ultimately to support JavaScript as well, as TypeScript's tooling can provide best-in-class support for both TS and JS projects.
{% endhint %}

[ember.js]: https://www.emberjs.com
[glimmerx]: https://github.com/glimmerjs/glimmer-experimental
[vetur]: https://github.com/vuejs/vetur
Expand Down