Skip to content

Commit

Permalink
Merge pull request #392 from dfreeman/fix-signature-expansion
Browse files Browse the repository at this point in the history
Fix `Signature` integration for external consumers
  • Loading branch information
chriskrycho committed Apr 8, 2022
2 parents febb6b8 + 43196ce commit ac1732e
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 2 deletions.
2 changes: 1 addition & 1 deletion packages/@glimmer/component/addon/-private/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ type _ExpandSignature<T> = {
Blocks: 'Blocks' extends keyof T
? {
[Block in keyof T['Blocks']]: T['Blocks'][Block] extends unknown[]
? { Positional: T['Blocks'][Block] }
? { Params: { Positional: T['Blocks'][Block] } }
: T['Blocks'][Block];
}
: EmptyObject;
Expand Down
7 changes: 7 additions & 0 deletions packages/@glimmer/component/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,13 @@
"typescript": "~4.2.3",
"webpack": "^5.69.0"
},
"typesVersions": {
"*": {
"-private/*": [
"dist/modules/addon/-private/*"
]
}
},
"engines": {
"node": "12.* || 14.* || >= 16"
},
Expand Down
92 changes: 91 additions & 1 deletion test/types/component-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import Component from '@glimmer/component';
// expect to be -- and this keeps us honest about the fact that if we *change*
// this import location, we've broken any existing declarations published using
// the current type signatures.
import { EmptyObject } from '@glimmer/component/addon/-private/component';
import type { EmptyObject, ExpandSignature } from '@glimmer/component/-private/component';

declare let basicComponent: Component;
expectTypeOf(basicComponent).toHaveProperty('args');
Expand All @@ -30,6 +30,12 @@ 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.
// Here, we are testing that the types propertly distribute over union types,
Expand All @@ -44,6 +50,19 @@ const legacyArgsDistributiveB = new Component<LegacyArgsDistributive>(
);
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 +86,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 +100,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: [name: string];
inverse: [];
Expand All @@ -88,6 +119,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: [name: string];
};
};
inverse: {
Params: {
Positional: [];
};
};
};
}>();

interface ArgsAndBlocks {
Args: LegacyArgs;
Blocks: Blocks;
Expand All @@ -96,6 +144,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: [name: string];
};
};
inverse: {
Params: {
Positional: [];
};
};
};
}>();

interface ArgsAndEl {
Args: LegacyArgs;
Element: HTMLParagraphElement;
Expand All @@ -104,6 +169,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 +184,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: [name: string];
};
};
inverse: {
Params: {
Positional: [];
};
};
};
}>();

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

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

expectTypeOf<ExpandSignature<FullLongSig>>().toEqualTypeOf<FullLongSig>();

0 comments on commit ac1732e

Please sign in to comment.