diff --git a/packages/@glimmer/component/addon/-private/component.ts b/packages/@glimmer/component/addon/-private/component.ts index 154d2edd2..d92fd1686 100644 --- a/packages/@glimmer/component/addon/-private/component.ts +++ b/packages/@glimmer/component/addon/-private/component.ts @@ -54,18 +54,7 @@ type ArgsFor = S extends { Args: infer Args } : { Named: S['Args']; Positional: [] } : { Named: EmptyObject; Positional: [] }; -/** - * Given any allowed shorthand form of a signature, desugars it to its full - * expanded type. - * - * @internal This is only exported so we can avoid duplicating it in - * [Glint](https://github.com/typed-ember/glint) or other such tooling. It is - * *not* intended for public usage, and the specific mechanics it uses may - * change at any time. Although the signature produced by is part of Glimmer's - * public API the existence and mechanics of this specific symbol are *not*, - * so ***DO NOT RELY ON IT***. - */ -export type ExpandSignature = { +type _ExpandSignature = { Element: GetOrElse; Args: keyof T extends 'Args' | 'Element' | 'Blocks' // Is this a `Signature`? ? ArgsFor // Then use `Signature` args @@ -74,11 +63,29 @@ export type ExpandSignature = { ? { [Block in keyof Blocks]: Blocks[Block] extends unknown[] ? { Positional: Blocks[Block] } - : Blocks[Block]; + : Blocks[Block] } : EmptyObject; }; +/** + * Given any allowed shorthand form of a signature, desugars it to its full + * expanded type. + * + * @internal This is only exported so we can avoid duplicating it in + * [Glint](https://github.com/typed-ember/glint) or other such tooling. It is + * *not* intended for public usage, and the specific mechanics it uses may + * change at any time. Although the signature produced by is part of Glimmer's + * public API the existence and mechanics of this specific symbol are *not*, + * so ***DO NOT RELY ON IT***. + */ +// The conditional type here is because TS applies conditional types +// distributively. This means that for union types, checks like `keyof T` get +// all the keys from all elements of the union, instead of ending up as `never` +// and then always falling into the `Signature` path instead of falling back to +// the legacy args handling path. +export type ExpandSignature = T extends any ? _ExpandSignature : never; + /** * @internal we use this type for convenience internally; inference means users * should not normally need to name it @@ -220,7 +227,9 @@ export default class BaseComponent { constructor(owner: unknown, args: Args) { if (DEBUG && !(owner !== null && typeof owner === 'object' && ARGS_SET.has(args))) { throw new Error( - `You must pass both the owner and args to super() in your component: ${this.constructor.name}. You can pass them directly, or use ...arguments to pass all arguments through.` + `You must pass both the owner and args to super() in your component: ${ + this.constructor.name + }. You can pass them directly, or use ...arguments to pass all arguments through.` ); }