Skip to content
This repository has been archived by the owner on Dec 13, 2018. It is now read-only.

Commit

Permalink
fix(typescript): fix component factory typings (#291)
Browse files Browse the repository at this point in the history
Glamorous component factory typings are now overloaded to accept
arguments in the following order of matching:

* style arguments with no Props
* style arguments with Props and a Theme
* style arguments with Props
  • Loading branch information
luke-john authored and Kent C. Dodds committed Aug 18, 2017
1 parent dd62082 commit f35d7b2
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 58 deletions.
44 changes: 22 additions & 22 deletions src/__tests__/__snapshots__/typescript.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -7,33 +7,33 @@ exports[`Typescript expected failures 1`] = `
test/should-fail.test.tsx(16,3): error TS2345: Argument of type '{ fillRule: \\"cat\\"; }' is not assignable to parameter of type 'StyleArgument<SVGProperties, {}>'.
Type '{ fillRule: \\"cat\\"; }' is not assignable to type '(string | Partial<SVGProperties> | StyleFunction<SVGProperties, {}>)[]'.
Property 'length' is missing in type '{ fillRule: \\"cat\\"; }'.
test/should-fail.test.tsx(22,3): error TS2345: Argument of type '() => { fillRule: \\"cat\\"; }' is not assignable to parameter of type 'StyleArgument<SVGProperties, {}>'.
Type '() => { fillRule: \\"cat\\"; }' is not assignable to type '(string | Partial<SVGProperties> | StyleFunction<SVGProperties, {}>)[]'.
Property 'push' is missing in type '() => { fillRule: \\"cat\\"; }'.
test/should-fail.test.tsx(22,3): error TS2345: Argument of type '() => { fillRule: string; }' is not assignable to parameter of type 'StyleArgument<SVGProperties, {}>'.
Type '() => { fillRule: string; }' is not assignable to type '(string | Partial<SVGProperties> | StyleFunction<SVGProperties, {}>)[]'.
Property 'push' is missing in type '() => { fillRule: string; }'.
test/should-fail.test.tsx(30,3): error TS2345: Argument of type '{ float: \\"cat\\"; }' is not assignable to parameter of type 'StyleArgument<CSSProperties, {}>'.
Type '{ float: \\"cat\\"; }' is not assignable to type '(string | Partial<CSSProperties> | StyleFunction<CSSProperties, {}>)[]'.
Property 'length' is missing in type '{ float: \\"cat\\"; }'.
test/should-fail.test.tsx(36,3): error TS2345: Argument of type '{ float: \\"cat\\"; }' is not assignable to parameter of type 'StyleArgument<CSSProperties, {}>'.
Type '{ float: \\"cat\\"; }' is not assignable to type '(string | Partial<CSSProperties> | StyleFunction<CSSProperties, {}>)[]'.
Property 'length' is missing in type '{ float: \\"cat\\"; }'.
test/should-fail.test.tsx(42,3): error TS2345: Argument of type '() => { float: \\"cat\\"; }' is not assignable to parameter of type 'StyleArgument<CSSProperties, {}>'.
Type '() => { float: \\"cat\\"; }' is not assignable to type '(string | Partial<CSSProperties> | StyleFunction<CSSProperties, {}>)[]'.
Property 'push' is missing in type '() => { float: \\"cat\\"; }'.
test/should-fail.test.tsx(48,3): error TS2345: Argument of type '() => { float: \\"cat\\"; }' is not assignable to parameter of type 'StyleArgument<CSSProperties, {}>'.
Type '() => { float: \\"cat\\"; }' is not assignable to type '(string | Partial<CSSProperties> | StyleFunction<CSSProperties, {}>)[]'.
Property 'push' is missing in type '() => { float: \\"cat\\"; }'.
test/should-fail.test.tsx(42,3): error TS2345: Argument of type '() => { float: string; }' is not assignable to parameter of type 'StyleArgument<CSSProperties, {}>'.
Type '() => { float: string; }' is not assignable to type '(string | Partial<CSSProperties> | StyleFunction<CSSProperties, {}>)[]'.
Property 'push' is missing in type '() => { float: string; }'.
test/should-fail.test.tsx(48,3): error TS2345: Argument of type '() => { float: string; }' is not assignable to parameter of type 'StyleArgument<CSSProperties, {}>'.
Type '() => { float: string; }' is not assignable to type '(string | Partial<CSSProperties> | StyleFunction<CSSProperties, {}>)[]'.
Property 'push' is missing in type '() => { float: string; }'.
test/should-fail.test.tsx(64,3): error TS2345: Argument of type '{ fillRule: \\"cat\\"; }' is not assignable to parameter of type 'StyleArgument<CSSProperties, TestComponentProps & object>'.
Type '{ fillRule: \\"cat\\"; }' is not assignable to type '(string | Partial<CSSProperties> | StyleFunction<CSSProperties, TestComponentProps & object>)[]'.
Property 'length' is missing in type '{ fillRule: \\"cat\\"; }'.
test/should-fail.test.tsx(70,3): error TS2345: Argument of type '() => { fillRule: \\"cat\\"; }' is not assignable to parameter of type 'StyleArgument<CSSProperties, TestComponentProps & object>'.
Type '() => { fillRule: \\"cat\\"; }' is not assignable to type '(string | Partial<CSSProperties> | StyleFunction<CSSProperties, TestComponentProps & object>)[]'.
Property 'push' is missing in type '() => { fillRule: \\"cat\\"; }'.
test/should-fail.test.tsx(70,3): error TS2345: Argument of type '() => { fillRule: string; }' is not assignable to parameter of type 'StyleArgument<CSSProperties, TestComponentProps & object>'.
Type '() => { fillRule: string; }' is not assignable to type '(string | Partial<CSSProperties> | StyleFunction<CSSProperties, TestComponentProps & object>)[]'.
Property 'push' is missing in type '() => { fillRule: string; }'.
test/should-fail.test.tsx(76,3): error TS2345: Argument of type '{ float: \\"cat\\"; }' is not assignable to parameter of type 'StyleArgument<CSSProperties, TestComponentProps & object>'.
Type '{ float: \\"cat\\"; }' is not assignable to type '(string | Partial<CSSProperties> | StyleFunction<CSSProperties, TestComponentProps & object>)[]'.
Property 'length' is missing in type '{ float: \\"cat\\"; }'.
test/should-fail.test.tsx(82,3): error TS2345: Argument of type '() => { float: \\"cat\\"; }' is not assignable to parameter of type 'StyleArgument<CSSProperties, TestComponentProps & object>'.
Type '() => { float: \\"cat\\"; }' is not assignable to type '(string | Partial<CSSProperties> | StyleFunction<CSSProperties, TestComponentProps & object>)[]'.
Property 'push' is missing in type '() => { float: \\"cat\\"; }'.
test/should-fail.test.tsx(82,3): error TS2345: Argument of type '() => { float: string; }' is not assignable to parameter of type 'StyleArgument<CSSProperties, TestComponentProps & object>'.
Type '() => { float: string; }' is not assignable to type '(string | Partial<CSSProperties> | StyleFunction<CSSProperties, TestComponentProps & object>)[]'.
Property 'push' is missing in type '() => { float: string; }'.
test/should-fail.test.tsx(100,24): error TS2551: Property 'colors' does not exist on type 'ExampleTheme'. Did you mean 'color'?
test/should-fail.test.tsx(111,3): error TS2344: Type 'PropsWithoutTheme' does not satisfy the constraint '{ theme: any; }'.
Property 'theme' is missing in type 'PropsWithoutTheme'.
Expand All @@ -47,11 +47,11 @@ test/should-fail.test.tsx(140,3): error TS2345: Argument of type '(props: { visi
Type '(props: { visible: boolean; } & object) => { display: \\"none\\" | \\"hidden\\"; }' is not assignable to type '(string | Partial<CSSProperties> | StyleFunction<CSSProperties, { visible: boolean; } & object>)[]'.
Property 'push' is missing in type '(props: { visible: boolean; } & object) => { display: \\"none\\" | \\"hidden\\"; }'.
test/should-fail.test.tsx(150,29): error TS2322: Type '{ visible: \\"string\\"; }' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<Component<ExtraGlamorousProps & ExampleComponentPr...'.
Type '{ visible: \\"string\\"; }' is not assignable to type 'Readonly<ExtraGlamorousProps & ExampleComponentProps & object & Pick<{ theme: any; }, never>>'.
Type '{ visible: \\"string\\"; }' is not assignable to type 'Readonly<ExtraGlamorousProps & ExampleComponentProps & object>'.
Types of property 'visible' are incompatible.
Type '\\"string\\"' is not assignable to type 'boolean'.
test/should-fail.test.tsx(151,5): error TS2322: Type '{}' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<Component<ExtraGlamorousProps & ExampleComponentPr...'.
Type '{}' is not assignable to type 'Readonly<ExtraGlamorousProps & ExampleComponentProps & object & Pick<{ theme: any; }, never>>'.
Type '{}' is not assignable to type 'Readonly<ExtraGlamorousProps & ExampleComponentProps & object>'.
Property 'visible' is missing in type '{}'.
test/should-fail.test.tsx(152,32): error TS2322: Type '{ visible: \\"string\\"; }' is not assignable to type '(IntrinsicAttributes & IntrinsicClassAttributes<Component<(ExtraGlamorousProps & BuiltInGlamorous...'.
Type '{ visible: \\"string\\"; }' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<Component<(ExtraGlamorousProps & BuiltInGlamorousC...'.
Expand Down Expand Up @@ -98,9 +98,9 @@ test/should-fail.test.tsx(260,31): error TS2322: Type '{ primaryColor: 1; }' is
Type '{ primaryColor: 1; }' is not assignable to type 'Readonly<ExtraGlamorousProps & Partial<{ primaryColor: string; }> & Pick<{ theme: any; }, never>>'.
Types of property 'primaryColor' are incompatible.
Type '1' is not assignable to type 'string | undefined'.
test/should-fail.test.tsx(261,31): error TS2559: Type '{ d: \\"\\"; }' has no properties in common with type 'IntrinsicAttributes & IntrinsicClassAttributes<Component<ExtraGlamorousProps & object & Pick<{ th...'.
test/should-fail.test.tsx(262,31): error TS2322: Type '{ primaryColor: 1; }' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<Component<ExtraGlamorousProps & object & Pick<{ th...'.
Type '{ primaryColor: 1; }' is not assignable to type 'Readonly<ExtraGlamorousProps & object & Pick<{ theme: any; }, never> & Partial<{ primaryColor: st...'.
test/should-fail.test.tsx(261,31): error TS2559: Type '{ d: \\"\\"; }' has no properties in common with type 'IntrinsicAttributes & IntrinsicClassAttributes<Component<ExtraGlamorousProps & object & Partial<{...'.
test/should-fail.test.tsx(262,31): error TS2322: Type '{ primaryColor: 1; }' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<Component<ExtraGlamorousProps & object & Partial<{...'.
Type '{ primaryColor: 1; }' is not assignable to type 'Readonly<ExtraGlamorousProps & object & Partial<{ primaryColor: string; }>>'.
Types of property 'primaryColor' are incompatible.
Type '1' is not assignable to type 'string | undefined'.
test/should-fail.test.tsx(267,15): error TS2345: Argument of type '{ textAlign: \\"center\\"; display: (\\"block\\" | \\"flexs\\")[]; }' is not assignable to parameter of type 'StyleArgument<CSSProperties, {}>'.
Expand All @@ -113,8 +113,8 @@ test/should-fail.test.tsx(289,35): error TS2322: Type '{ display: \\"blocks\\";
Type '{ display: \\"blocks\\"; }' is not assignable to type 'Readonly<ExtraGlamorousProps & object & SingleOrArray<CSSPropertiesCompleteSingle, \\"left\\" | \\"righ...'.
Types of property 'display' are incompatible.
Type '\\"blocks\\"' is not assignable to type '\\"none\\" | \\"table\\" | \\"ruby\\" | \\"initial\\" | \\"inherit\\" | \\"unset\\" | \\"block\\" | \\"inline\\" | \\"run-in\\" | \\"fl...'.
test/should-fail.test.tsx(290,38): error TS2559: Type '{ display: \\"block\\"; }' has no properties in common with type 'IntrinsicAttributes & IntrinsicClassAttributes<Component<ExtraGlamorousProps & object & Pick<{ th...'.
test/should-fail.test.tsx(291,42): error TS2559: Type '{ display: \\"block\\"; }' has no properties in common with type 'IntrinsicAttributes & IntrinsicClassAttributes<Component<ExtraGlamorousProps & object & Pick<{ th...'.
test/should-fail.test.tsx(290,38): error TS2559: Type '{ display: \\"block\\"; }' has no properties in common with type 'IntrinsicAttributes & IntrinsicClassAttributes<Component<ExtraGlamorousProps & object, ComponentS...'.
test/should-fail.test.tsx(291,42): error TS2559: Type '{ display: \\"block\\"; }' has no properties in common with type 'IntrinsicAttributes & IntrinsicClassAttributes<Component<ExtraGlamorousProps & object, ComponentS...'.
test/should-fail.test.tsx(293,29): error TS2322: Type '{ display: \\"blocks\\"; }' is not assignable to type '(IntrinsicAttributes & IntrinsicClassAttributes<Component<(ExtraGlamorousProps & BuiltInGlamorous...'.
Type '{ display: \\"blocks\\"; }' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<Component<(ExtraGlamorousProps & BuiltInGlamorousC...'.
Type '{ display: \\"blocks\\"; }' is not assignable to type 'Readonly<ExtraGlamorousProps & BuiltInGlamorousComponentFactory<HTMLProps<HTMLVideoElement>, CSSP...'.
Expand Down
89 changes: 54 additions & 35 deletions typings/component-factory.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,32 @@
import { GlamorousComponent } from './glamorous-component'
import { Omit } from './helpers'

import { StyleArgument } from './style-arguments'
import { StyleArgument, StaticStyleArgument } from './style-arguments'

// # built-in DOM - component factories glamorous.div

// * without Theme
export interface BuiltInGlamorousComponentFactory<ElementProps, Properties> {
<Props>(
...styles: StyleArgument<Properties, Props>[]
(
...styles: StaticStyleArgument<Properties>[]
): GlamorousComponent<
ElementProps & Props,
Props
ElementProps,
object
>;
}

// * with Theme
export interface BuiltInGlamorousComponentFactory<ElementProps, Properties> {
<Props extends { theme: any }>(
...styles: StyleArgument<Properties, Props>[]
): GlamorousComponent<
ElementProps & Omit<Props, 'theme'>,
Props
>;

<Props>(
...styles: StyleArgument<Properties, Props>[]
): GlamorousComponent<
ElementProps & Props,
Props
>;
}

// # dom tag - component factories glamorous('div')
Expand All @@ -31,45 +35,52 @@ export interface BuiltInGlamorousComponentFactory<ElementProps, Properties> {

// * without Theme
export interface KeyGlamorousComponentFactory<ElementProps, Properties, ExternalProps, DefaultProps> {
<Props>(
...styles: StyleArgument<Properties, Props & ExternalProps & DefaultProps>[]
(
...styles: StaticStyleArgument<Properties>[]
): GlamorousComponent<
ElementProps & ExternalProps & Partial<DefaultProps> & Props,
ElementProps & ExternalProps & Partial<DefaultProps>,
ExternalProps
>;
}


// * with Theme
export interface KeyGlamorousComponentFactory<ElementProps, Properties, ExternalProps, DefaultProps> {
<Props extends { theme?: any }>(
...styles: StyleArgument<Properties, Props & ExternalProps & DefaultProps>[]
): GlamorousComponent<
ElementProps & ExternalProps & Partial<DefaultProps> & Omit<Props, 'theme'> & Props,
ExternalProps
>;

<Props>(
...styles: StyleArgument<Properties, Props & ExternalProps & DefaultProps>[]
): GlamorousComponent<
ElementProps & ExternalProps & Partial<DefaultProps> & Props,
ExternalProps
>;
}

// ## with propsAreCssOverides

// * without Theme
export interface KeyGlamorousComponentFactoryCssOverides<ElementProps, Properties, ExternalProps, DefaultProps> {
<Props>(
...styles: StyleArgument<Properties, Props & ExternalProps & DefaultProps>[]
(
...styles: StaticStyleArgument<Properties>[]
): GlamorousComponent<
ElementProps & ExternalProps & Partial<DefaultProps> & Props & Properties,
ElementProps & ExternalProps & Partial<DefaultProps> & Properties,
ExternalProps
>;
}

// * with Theme
export interface KeyGlamorousComponentFactoryCssOverides<ElementProps, Properties, ExternalProps, DefaultProps> {
<Props extends { theme?: any }>(
...styles: StyleArgument<Properties, Props & ExternalProps & DefaultProps>[]
): GlamorousComponent<
ElementProps & ExternalProps & Partial<DefaultProps> & Omit<Props, 'theme'> & Properties,
ExternalProps
>;

<Props>(
...styles: StyleArgument<Properties, Props & ExternalProps & DefaultProps>[]
): GlamorousComponent<
ElementProps & ExternalProps & Partial<DefaultProps> & Props & Properties,
ExternalProps
>;
}

// # react component - component factories glamorous(Component)
Expand All @@ -78,42 +89,50 @@ export interface KeyGlamorousComponentFactoryCssOverides<ElementProps, Propertie

// * without Theme
export interface GlamorousComponentFactory<ExternalProps, Properties, DefaultProps> {
<Props>(
...styles: StyleArgument<Properties, Props & ExternalProps & DefaultProps>[]
(
...styles: StaticStyleArgument<Properties>[]
): GlamorousComponent<
ExternalProps & Partial<DefaultProps> & Props,
Props
ExternalProps & Partial<DefaultProps>,
object
>;
}

// * with Theme
export interface GlamorousComponentFactory<ExternalProps, Properties, DefaultProps> {
<Props extends { theme: any }>(
...styles: StyleArgument<Properties, Props & ExternalProps & DefaultProps>[]
): GlamorousComponent<
ExternalProps & Partial<DefaultProps> & Omit<Props, 'theme'>,
Props
>;

<Props>(
...styles: StyleArgument<Properties, Props & ExternalProps & DefaultProps>[]
): GlamorousComponent<
ExternalProps & Partial<DefaultProps> & Props,
Props
>;
}

// ## with propsAreCssOverides

// * without Theme
export interface GlamorousComponentFactoryCssOverides<ExternalProps, Properties, DefaultProps> {
<Props>(
...styles: StyleArgument<Properties, Props & ExternalProps & DefaultProps>[]
(
...styles: StaticStyleArgument<Properties>[]
): GlamorousComponent<
ExternalProps & Partial<DefaultProps> & Properties & Props,
Props
ExternalProps & Partial<DefaultProps> & Properties,
object
>
}

// * with Theme
export interface GlamorousComponentFactoryCssOverides<ExternalProps, Properties, DefaultProps> {
<Props extends { theme: any }>(
...styles: StyleArgument<Properties, Props & ExternalProps & DefaultProps>[]
): GlamorousComponent<
ExternalProps & Partial<DefaultProps> & Properties & Omit<Props, 'theme'>,
Props
>

<Props>(
...styles: StyleArgument<Properties, Props & ExternalProps & DefaultProps>[]
): GlamorousComponent<
ExternalProps & Partial<DefaultProps> & Properties & Props,
Props
>
}
12 changes: 11 additions & 1 deletion typings/style-arguments.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,18 @@ export type StyleArray<Properties, Props> = Array<
| StyleFunction<Properties, Props>
>

export type StaticStyleArray<Properties> = Array<
| Partial<Properties>
| string
>

export type StyleArgument<Properties, Props> =
| Partial<Properties>
| string
| StyleFunction<Properties, Props>
| StyleArray<Properties, Props>
| StyleArray<Properties, Props>

export type StaticStyleArgument<Properties> =
| Partial<Properties>
| string
| StaticStyleArray<Properties>

0 comments on commit f35d7b2

Please sign in to comment.