Skip to content

Commit

Permalink
Merge pull request #393 from dfreeman/backport-392
Browse files Browse the repository at this point in the history
Backport: Fix `Signature` integration for external consumers
  • Loading branch information
chriskrycho committed Apr 8, 2022
2 parents d0b7752 + f1c905c commit 824dcfb
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 5 deletions.
4 changes: 2 additions & 2 deletions packages/@glimmer/component/addon/-private/component.ts
Expand Up @@ -62,8 +62,8 @@ type _ExpandSignature<T> = {
Blocks: T extends { Blocks: infer Blocks }
? {
[Block in keyof Blocks]: Blocks[Block] extends unknown[]
? { Positional: Blocks[Block] }
: Blocks[Block]
? { Params: { Positional: Blocks[Block] } }
: Blocks[Block];
}
: EmptyObject;
};
Expand Down
9 changes: 8 additions & 1 deletion packages/@glimmer/component/package.json
Expand Up @@ -85,6 +85,13 @@
"qunit-dom": "^0.7.1",
"typescript": "~3.5.3"
},
"typesVersions": {
"*": {
"-private/*": [
"dist/types/addon/-private/*"
]
}
},
"engines": {
"node": "6.* || 8.* || >= 10.*"
},
Expand All @@ -93,4 +100,4 @@
"defaultBlueprint": "install-glimmer-component",
"main": "ember-addon-main.js"
}
}
}
97 changes: 95 additions & 2 deletions test/types/component-test.ts
Expand Up @@ -12,7 +12,7 @@ import Component from '@glimmer/component';
// matches the actual import location to which this type would be emitted. Since
// this is an internal-only type whose presence consumers should not rely on and
// which they should not use in any way, this is "safe" from a public API POV.
import { EmptyObject } from '@glimmer/component/dist/types/addon/-private/component';
import { EmptyObject, ExpandSignature } from '@glimmer/component/-private/component';

declare let basicComponent: Component;
expectTypeOf(basicComponent).toHaveProperty('args');
Expand All @@ -33,15 +33,37 @@ type LegacyArgs = {
const componentWithLegacyArgs = new Component<LegacyArgs>({}, { foo: 123 });
expectTypeOf(componentWithLegacyArgs.args).toEqualTypeOf<Readonly<LegacyArgs>>();

expectTypeOf<ExpandSignature<LegacyArgs>>().toEqualTypeOf<{
Args: { Named: LegacyArgs; Positional: [] };
Element: null;
Blocks: EmptyObject;
}>();

// Here, we are testing that the types propertly distribute over union types,
// generics which extend other types, etc.
type LegacyArgsDistributive = { foo: number } | { bar: string; baz: boolean };

const legacyArgsDistributiveA = new Component<LegacyArgsDistributive>({}, { foo: 123 });
expectTypeOf(legacyArgsDistributiveA.args).toEqualTypeOf<Readonly<LegacyArgsDistributive>>();
const legacyArgsDistributiveB = new Component<LegacyArgsDistributive>({}, { bar: "hello", baz: true });
const legacyArgsDistributiveB = new Component<LegacyArgsDistributive>(
{},
{ bar: 'hello', baz: true }
);
expectTypeOf(legacyArgsDistributiveB.args).toEqualTypeOf<Readonly<LegacyArgsDistributive>>();

expectTypeOf<ExpandSignature<LegacyArgsDistributive>>().toEqualTypeOf<
| {
Args: { Named: { foo: number }; Positional: [] };
Element: null;
Blocks: EmptyObject;
}
| {
Args: { Named: { bar: string; baz: boolean }; Positional: [] };
Element: null;
Blocks: EmptyObject;
}
>();

interface ExtensibleLegacy<T> {
value: T;
extras: boolean;
Expand All @@ -67,6 +89,12 @@ interface ArgsOnly {
const componentWithArgsOnly = new Component<ArgsOnly>({}, { foo: 123 });
expectTypeOf(componentWithArgsOnly.args).toEqualTypeOf<Readonly<LegacyArgs>>();

expectTypeOf<ExpandSignature<ArgsOnly>>().toEqualTypeOf<{
Args: { Named: LegacyArgs; Positional: [] };
Element: null;
Blocks: EmptyObject;
}>();

interface ElementOnly {
Element: HTMLParagraphElement;
}
Expand All @@ -75,6 +103,12 @@ const componentWithElOnly = new Component<ElementOnly>({}, {});

expectTypeOf(componentWithElOnly.args).toEqualTypeOf<Readonly<EmptyObject>>();

expectTypeOf<ExpandSignature<ElementOnly>>().toEqualTypeOf<{
Args: { Named: EmptyObject; Positional: [] };
Element: HTMLParagraphElement;
Blocks: EmptyObject;
}>();

interface Blocks {
default: [string];
inverse: [];
Expand All @@ -88,6 +122,23 @@ const componentWithBlockOnly = new Component<BlockOnlySig>({}, {});

expectTypeOf(componentWithBlockOnly.args).toEqualTypeOf<Readonly<EmptyObject>>();

expectTypeOf<ExpandSignature<BlockOnlySig>>().toEqualTypeOf<{
Args: { Named: EmptyObject; Positional: [] };
Element: null;
Blocks: {
default: {
Params: {
Positional: [string];
};
};
inverse: {
Params: {
Positional: [];
};
};
};
}>();

interface ArgsAndBlocks {
Args: LegacyArgs;
Blocks: Blocks;
Expand All @@ -96,6 +147,23 @@ interface ArgsAndBlocks {
const componentwithArgsAndBlocks = new Component<ArgsAndBlocks>({}, { foo: 123 });
expectTypeOf(componentwithArgsAndBlocks.args).toEqualTypeOf<Readonly<LegacyArgs>>();

expectTypeOf<ExpandSignature<ArgsAndBlocks>>().toEqualTypeOf<{
Args: { Named: LegacyArgs; Positional: [] };
Element: null;
Blocks: {
default: {
Params: {
Positional: [string];
};
};
inverse: {
Params: {
Positional: [];
};
};
};
}>();

interface ArgsAndEl {
Args: LegacyArgs;
Element: HTMLParagraphElement;
Expand All @@ -104,6 +172,12 @@ interface ArgsAndEl {
const componentwithArgsAndEl = new Component<ArgsAndEl>({}, { foo: 123 });
expectTypeOf(componentwithArgsAndEl.args).toEqualTypeOf<Readonly<LegacyArgs>>();

expectTypeOf<ExpandSignature<ArgsAndEl>>().toEqualTypeOf<{
Args: { Named: LegacyArgs; Positional: [] };
Element: HTMLParagraphElement;
Blocks: EmptyObject;
}>();

interface FullShortSig {
Args: LegacyArgs;
Element: HTMLParagraphElement;
Expand All @@ -113,6 +187,23 @@ interface FullShortSig {
const componentWithFullShortSig = new Component<FullShortSig>({}, { foo: 123 });
expectTypeOf(componentWithFullShortSig.args).toEqualTypeOf<Readonly<LegacyArgs>>();

expectTypeOf<ExpandSignature<FullShortSig>>().toEqualTypeOf<{
Args: { Named: LegacyArgs; Positional: [] };
Element: HTMLParagraphElement;
Blocks: {
default: {
Params: {
Positional: [string];
};
};
inverse: {
Params: {
Positional: [];
};
};
};
}>();

interface FullLongSig {
Args: {
Named: LegacyArgs;
Expand All @@ -130,3 +221,5 @@ interface FullLongSig {

const componentWithFullSig = new Component<FullLongSig>({}, { foo: 123 });
expectTypeOf(componentWithFullSig.args).toEqualTypeOf<Readonly<LegacyArgs>>();

expectTypeOf<ExpandSignature<FullLongSig>>().toEqualTypeOf<FullLongSig>();
4 changes: 4 additions & 0 deletions test/types/tsconfig.json
Expand Up @@ -31,6 +31,10 @@
"noEmit": true,

"paths": {
"@glimmer/component/-private/*": [
// This must match the `typesVersions` entry in `@glimmer/component`'s package.json
"../../dist/@glimmer/component/dist/types/addon/-private/*"
],
"@glimmer/*": ["../../dist/@glimmer/*"]
}
}
Expand Down

0 comments on commit 824dcfb

Please sign in to comment.