diff --git a/packages/typescript-plugin/src/typescript-server-plugin.ts b/packages/typescript-plugin/src/typescript-server-plugin.ts
index 2831ebfa..140d9d9f 100644
--- a/packages/typescript-plugin/src/typescript-server-plugin.ts
+++ b/packages/typescript-plugin/src/typescript-server-plugin.ts
@@ -10,7 +10,9 @@ const {
const plugin = createAsyncLanguageServicePlugin(
['.gts', '.gjs', '.hbs'],
(fileName: string) => {
- if (fileName.endsWith('.gts')) {
+ if (fileName.endsWith('.hbs')) {
+ return 3 satisfies ts.ScriptKind.TS;
+ } else if (fileName.endsWith('.gts')) {
return 3 satisfies ts.ScriptKind.TS;
} else if (fileName.endsWith('.gjs')) {
return 1 satisfies ts.ScriptKind.JS;
diff --git a/packages/vscode/package.json b/packages/vscode/package.json
index 446a2d8d..4f3b1e85 100644
--- a/packages/vscode/package.json
+++ b/packages/vscode/package.json
@@ -162,6 +162,7 @@
{
"name": "@glint/typescript-plugin",
"enableForWorkspaceTypeScriptVersions": true,
+ "configNamespace": "typescript",
"languages": [
"glimmer-ts",
"glimmer-js"
diff --git a/test-packages/ts-plugin-test-app/package.json b/test-packages/ts-plugin-test-app/package.json
index be7b4714..7c39b307 100644
--- a/test-packages/ts-plugin-test-app/package.json
+++ b/test-packages/ts-plugin-test-app/package.json
@@ -10,6 +10,8 @@
"description": "",
"devDependencies": {
"typescript": "*",
+ "@glint/core": "*",
+ "@glint/environment-ember-loose": "*",
"@glint/typescript-plugin": "*"
}
}
diff --git a/test-packages/ts-plugin-test-app/src/ember-component.hbs b/test-packages/ts-plugin-test-app/src/ember-component.hbs
index 7dd4f4d0..f622e109 100644
--- a/test-packages/ts-plugin-test-app/src/ember-component.hbs
+++ b/test-packages/ts-plugin-test-app/src/ember-component.hbs
@@ -1,6 +1,28 @@
-{{! TODO: this isn't working yet }}
-{{foo}}
+
+ {{this.required}}
+ {{this.optional}}
+ {{this.hasDefault}}
-
- {{this.bar}}
-
\ No newline at end of file
+ {{@required}}
+ {{@optional}}
+ {{@hasDefault}}
+
+ {{!--
+ This pair of checks needs to work in this app, which uses DT types, and the
+ preview/stable types app which does *not*.
+ --}}
+ {{get this "required"}}
+
+ {{! @glint-expect-error: non-existent property }}
+ {{get this "unrelated"}}
+
+
+{{#if this.showFunctionHelpers}}
+ {{! @glint-expect-error: missing arg }}
+ {{this.isLongString}}
+
+ {{! @glint-expect-error: wrong arg type }}
+ {{this.isLongString 123}}
+
+ {{this.isLongString 'hi'}}
+{{/if}}
\ No newline at end of file
diff --git a/test-packages/ts-plugin-test-app/src/ember-component.ts b/test-packages/ts-plugin-test-app/src/ember-component.ts
index 969e2955..6513e079 100644
--- a/test-packages/ts-plugin-test-app/src/ember-component.ts
+++ b/test-packages/ts-plugin-test-app/src/ember-component.ts
@@ -1,3 +1,38 @@
-export default class EmberComponent {
- foo = 123;
+/* eslint-disable ember/no-classic-components, ember/require-tagless-components */
+import Component from '@ember/component';
+
+export interface EmberComponentArgs {
+ required: string;
+ hasDefault?: string;
+ optional?: number;
+}
+
+export interface EmberComponentSignature {
+ Element: HTMLDivElement;
+ Args: EmberComponentArgs;
+}
+
+export default interface EmberComponent extends EmberComponentArgs {}
+export default class EmberComponent extends Component {
+ public hasDefault = 'defaultValue';
+ public showFunctionHelpers = false;
+
+ public isLongString(value: string): boolean {
+ return value.length > 5;
+ }
+
+ public checkTypes(): unknown {
+ const required: string = this.required;
+ const hasDefault: string = this.hasDefault;
+ const optional: number | undefined = this.optional;
+
+ return { required, hasDefault, optional };
+ }
+}
+
+declare module '@glint/environment-ember-loose/registry' {
+ export default interface Registry {
+ EmberComponent: typeof EmberComponent;
+ 'ember-component': typeof EmberComponent;
+ }
}
diff --git a/test-packages/ts-plugin-test-app/src/js-component.hbs b/test-packages/ts-plugin-test-app/src/js-component.hbs
new file mode 100644
index 00000000..324e005b
--- /dev/null
+++ b/test-packages/ts-plugin-test-app/src/js-component.hbs
@@ -0,0 +1 @@
+{{this.message}}
\ No newline at end of file
diff --git a/test-packages/ts-plugin-test-app/src/js-component.js b/test-packages/ts-plugin-test-app/src/js-component.js
new file mode 100644
index 00000000..4cdfaaef
--- /dev/null
+++ b/test-packages/ts-plugin-test-app/src/js-component.js
@@ -0,0 +1,5 @@
+import Component from '@glimmer/component';
+
+export default class MyComponent extends Component {
+ message = 'hi';
+}
diff --git a/test-packages/ts-plugin-test-app/src/wrapper-component.hbs b/test-packages/ts-plugin-test-app/src/wrapper-component.hbs
new file mode 100644
index 00000000..8db3d908
--- /dev/null
+++ b/test-packages/ts-plugin-test-app/src/wrapper-component.hbs
@@ -0,0 +1 @@
+{{yield (hash InnerComponent=(component "ember-component" required=@value))}}
diff --git a/test-packages/ts-plugin-test-app/src/wrapper-component.ts b/test-packages/ts-plugin-test-app/src/wrapper-component.ts
new file mode 100644
index 00000000..c107f285
--- /dev/null
+++ b/test-packages/ts-plugin-test-app/src/wrapper-component.ts
@@ -0,0 +1,28 @@
+/* eslint-disable ember/no-classic-components, ember/require-tagless-components */
+import { ComponentLike, WithBoundArgs } from '@glint/template';
+import Component from '@ember/component';
+import EmberComponent from './ember-component';
+
+interface WrapperComponentSignature {
+ Element: HTMLDivElement;
+ Args: {
+ value: string;
+ };
+ Blocks: {
+ default: [
+ {
+ InnerComponent: WithBoundArgs;
+ MaybeComponent?: ComponentLike<{ Args: { key: string } }>;
+ stringValue?: string;
+ },
+ ];
+ };
+}
+
+export default class WrapperComponent extends Component {}
+
+declare module '@glint/environment-ember-loose/registry' {
+ export default interface Registry {
+ WrapperComponent: typeof WrapperComponent;
+ }
+}