UNPKG

@glint/environment-ember-loose

Version:

A Glint environment to support loose-mode Ember.js projects

117 lines (92 loc) 3.62 kB
// This module is responsible for augmenting the upstream definitions of entities that interact // with templates to include the information necessary for Glint to typecheck them. import { ComponentLike, HelperLike, ModifierLike } from '@glint/template'; import { Context, FlattenBlockParams, HasContext, TemplateContext, } from '@glint/template/-private/integration'; import { ComponentSignatureArgs, ComponentSignatureBlocks, ComponentSignatureElement, } from '@glint/template/-private/signature'; ////////////////////////////////////////////////////////////////////// // Components import '@ember/component'; import '@ember/component/template-only'; import '@glimmer/component'; type ComponentContext<This, S> = TemplateContext< This, ComponentSignatureArgs<S>['Named'], FlattenBlockParams<ComponentSignatureBlocks<S>>, ComponentSignatureElement<S> >; declare module '@glimmer/component' { export default interface Component<S> extends InstanceType<ComponentLike<S>> { [Context]: ComponentContext<this, S>; } } declare module '@ember/component' { export default interface Component<S> extends InstanceType<ComponentLike<S>> { [Context]: ComponentContext<this, S>; } } interface TemplateOnlyComponentInstance<S> extends InstanceType<ComponentLike<S>> { [Context]: ComponentContext<null, S>; } // As with other abstract constructor types, this allows us to provide a class // and therefore have InstanceType work as needed, while forbidding construction // by end users. type TemplateOnlyConstructor<S> = abstract new () => TemplateOnlyComponentInstance<S>; declare module '@ember/component/template-only' { export interface TemplateOnlyComponent<S> extends TemplateOnlyConstructor<S> {} } ////////////////////////////////////////////////////////////////////// // Helpers import '@ember/component/helper'; declare module '@ember/component/helper' { export default interface Helper<S> extends InstanceType<HelperLike<S>> {} } ////////////////////////////////////////////////////////////////////// // Modifiers import 'ember-modifier'; declare module 'ember-modifier' { export default interface ClassBasedModifier<S> extends InstanceType<ModifierLike<S>> {} } ////////////////////////////////////////////////////////////////////// // Routes and Controllers import Controller from '@ember/controller'; import Route from '@ember/routing/route'; type ModelForRoute<T extends Route> = Awaited<ReturnType<T['model']>>; type ModelField<T> = { model: T }; declare module '@ember/routing/route' { export default interface Route { [Context]: TemplateContext< Controller & ModelField<ModelForRoute<this>>, ModelField<ModelForRoute<this>>, {}, null >; } } declare module '@ember/controller' { export default interface Controller { [Context]: TemplateContext<this, ModelField<this['model']>, {}, null>; } } ////////////////////////////////////////////////////////////////////// // Rendering Tests import '@ember/test-helpers'; import 'ember-cli-htmlbars'; type TestTemplate<T> = abstract new () => HasContext<TemplateContext<T, {}, {}, void>>; declare module '@ember/test-helpers' { export function render<T>(template: TestTemplate<T>): Promise<void>; } // Declaring that `TemplateFactory` is a valid `TestTemplate` prevents vanilla `tsc` from freaking out // about `hbs` not returning a valid type for `render`. Glint itself will never see `hbs` get used, as // it's transformed to the template DSL before typechecking. declare module 'ember-cli-htmlbars' { interface TemplateFactory extends TestTemplate<any> {} }