@glint/template 0.7.3 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -33,7 +33,7 @@ import { ResolveOrReturn } from './types';
33
33
 
34
34
  export declare function resolve<T extends DirectInvokable>(item: T): T[typeof InvokeDirect];
35
35
  export declare function resolve<Args extends unknown[], Instance extends Invokable>(
36
- item: (new (...args: Args) => Instance) | null | undefined
36
+ item: (abstract new (...args: Args) => Instance) | null | undefined
37
37
  ): (...args: Parameters<Instance[typeof Invoke]>) => ReturnType<Instance[typeof Invoke]>;
38
38
 
39
39
  /*
@@ -1,6 +1,6 @@
1
1
  import { EmptyObject, HasContext } from '@glint/template/-private/integration';
2
2
 
3
- type Constructor<T> = new (...args: any) => T;
3
+ type Constructor<T> = abstract new (...args: never[]) => T;
4
4
 
5
5
  /**
6
6
  * A utility for constructing the type of an environment's `resolveOrReturn` from
@@ -0,0 +1,114 @@
1
+ import {
2
+ AcceptsBlocks,
3
+ AnyFunction,
4
+ BoundModifier,
5
+ EmptyObject,
6
+ FlattenBlockParams,
7
+ Invokable,
8
+ } from './integration';
9
+ import { ExpandSignature } from '@glimmer/component/-private/component';
10
+
11
+ /**
12
+ * A value that is invokable like a component in a template. In an
13
+ * appropriate Glint environment, subclasses of `EmberComponent` and
14
+ * `GlimmerComponent` are examples of `ComponentLike` values, as are
15
+ * the values returned from the `{{component}}` helper.
16
+ *
17
+ * The `S` signature paramter here is of the same form as the one
18
+ * accepted by both the Ember and Glimmer `Component` base classes.
19
+ */
20
+ export type ComponentLike<S = unknown> = InvokableConstructor<
21
+ (
22
+ named: ExpandSignature<S>['Args']['Named'],
23
+ ...positional: ExpandSignature<S>['Args']['Positional']
24
+ ) => AcceptsBlocks<
25
+ FlattenBlockParams<ExpandSignature<S>['Blocks']>,
26
+ ExpandSignature<S>['Element']
27
+ >
28
+ >;
29
+
30
+ /**
31
+ * A value that is invokable like a helper in a template. Notably,
32
+ * subclasses of `Helper` and the return value of `helper()` from
33
+ * `@ember/component/helper` are both `HelperLike` in an appropriate
34
+ * Glint environment.
35
+ *
36
+ * The `S` signature parameter here is of the same form as the one
37
+ * accepted by `Helper` and `helper`.
38
+ */
39
+ export type HelperLike<S = unknown> = InvokableConstructor<
40
+ (...args: InvokableArgs<S>) => Get<S, 'Return', unknown>
41
+ >;
42
+
43
+ /**
44
+ * A value that is invokable like a modifier in a template. Notably,
45
+ * subclasses of `Modifier` and the return value of `modifier()` from
46
+ * `ember-modifier` are both `ModifierLike` in an appropriate Glint
47
+ * environment.
48
+ *
49
+ * The `S` signature parameter here is of the same form as the ones
50
+ * accepted by `Modifier` and `modifier`.
51
+ */
52
+ export type ModifierLike<S = unknown> = InvokableConstructor<
53
+ (...args: InvokableArgs<S>) => BoundModifier<Constrain<Get<S, 'Element'>, Element>>
54
+ >;
55
+
56
+ /**
57
+ * Given a `ComponentLike`, `HelperLike` or `ModifierLike` value
58
+ * along with a union representing named args that have been
59
+ * pre-bound, this helper returns the same item back, but with those
60
+ * named arguments made optional.
61
+ *
62
+ * This is typically useful in conjunction with something like the
63
+ * `{{component}}` helper; for instance, if you wrote this in a
64
+ * template:
65
+ *
66
+ * ```handlebars
67
+ * {{yield (component MyComponent message="Hello")}}
68
+ * ```
69
+ *
70
+ * Consumers of that yielded value would be able to invoke the
71
+ * component without having to provide a value for `@message`
72
+ * themselves. You could represent this in your signature as:
73
+ *
74
+ * ```ts
75
+ * Blocks: {
76
+ * default: [WithBoundArgs<typeof MyComponent, 'message'>];
77
+ * };
78
+ * ```
79
+ *
80
+ * If you had instead just written `default: [typeof MyComponent]`,
81
+ * consumers would still be obligated to provide a `@message`
82
+ * arg when invoking the yielded component.
83
+ */
84
+ export type WithBoundArgs<
85
+ T extends InvokableConstructor<AnyFunction>,
86
+ BoundArgs extends NamedArgNames<T>
87
+ > = T extends InvokableConstructor<
88
+ (named: infer Named, ...positional: infer Positional) => infer Result
89
+ >
90
+ ? InvokableConstructor<
91
+ (
92
+ named: Omit<Named, BoundArgs> & Partial<Pick<Named, BoundArgs & keyof Named>>,
93
+ ...positional: Positional
94
+ ) => Result
95
+ >
96
+ : never;
97
+
98
+ type InvokableConstructor<F extends AnyFunction> = abstract new (...args: any) => Invokable<F>;
99
+ type NamedArgNames<T extends InvokableConstructor<AnyFunction>> = T extends InvokableConstructor<
100
+ (named: infer Named, ...positional: any) => any
101
+ >
102
+ ? keyof Named
103
+ : never;
104
+
105
+ type Get<T, K, Otherwise = unknown> = K extends keyof T ? T[K] : Otherwise;
106
+ type Constrain<T, Constraint, Otherwise = Constraint> = T extends Constraint ? T : Otherwise;
107
+
108
+ // We use the imported `ExpandSignature` for component signatures, as they have
109
+ // different layers of possible shorthand, but modifiers and helpers only have
110
+ // one structure they can specify their args in, so this utility is sufficient.
111
+ type InvokableArgs<S> = [
112
+ named: Get<Get<S, 'Args'>, 'Named', EmptyObject>,
113
+ ...positional: Constrain<Get<Get<S, 'Args'>, 'Positional'>, Array<unknown>, []>
114
+ ];
@@ -37,8 +37,8 @@ export type BoundModifier<El extends Element> = { [Modifier]: (el: El) => void }
37
37
  * Denotes that the associated entity may be invoked with the given
38
38
  * blocks, yielding params of the appropriate type.
39
39
  */
40
- export type AcceptsBlocks<BlockImpls, El extends Element | null = null> = {
41
- [Element]: El;
40
+ export type AcceptsBlocks<BlockImpls, El = null> = {
41
+ [Element]: El extends Element ? El : null;
42
42
  (blocks: BlockImpls): { [Blocks]: true };
43
43
  };
44
44
 
@@ -52,3 +52,11 @@ export type TemplateContext<This, Args, Yields, Element> = {
52
52
  yields: Yields;
53
53
  element: Element;
54
54
  };
55
+
56
+ /**
57
+ * Flattens the fully expanded signature format for Blocks down to a mapping from
58
+ * each block name to a corresponding tuple of parameter types.
59
+ */
60
+ export type FlattenBlockParams<T> = {
61
+ [K in keyof T]: T[K] extends { Params: { Positional: infer U } } ? U : T[K];
62
+ };
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@glint/template",
3
- "version": "0.7.3",
3
+ "version": "0.8.0",
4
4
  "repository": "typed-ember/glint",
5
5
  "description": "Type definitions to back typechecking for Glimmer templates",
6
6
  "license": "MIT",
7
7
  "author": "Dan Freeman (https://github.com/dfreeman)",
8
- "types": "index.d.ts",
8
+ "types": "-private/index.d.ts",
9
9
  "scripts": {
10
10
  "lint": "eslint . --max-warnings 0 && prettier --check .",
11
11
  "test": "tsc --project __tests__"
@@ -15,10 +15,13 @@
15
15
  "-private",
16
16
  "*.d.ts"
17
17
  ],
18
+ "peerDependencies": {
19
+ "@glimmer/component": "^1.1.2"
20
+ },
18
21
  "devDependencies": {
19
- "@glimmer/component": "^1.1.0",
22
+ "@glimmer/component": "^1.1.2",
20
23
  "@glimmerx/component": "^0.4.2",
21
- "@types/ember__component": "~4.0.0",
24
+ "@types/ember__component": "~4.0.8",
22
25
  "expect-type": "0.11.0",
23
26
  "sums-up": "^2.1.0"
24
27
  },