From ccc955db4a52ace8deee2de5254ea1478dec2fd3 Mon Sep 17 00:00:00 2001 From: Anton Golub Date: Tue, 6 Apr 2021 11:25:17 +0300 Subject: [PATCH 01/25] chore(style): let StyledOptions generic argument be optional --- packages/styled/types/base.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/styled/types/base.d.ts b/packages/styled/types/base.d.ts index cf3063dba..c40430836 100644 --- a/packages/styled/types/base.d.ts +++ b/packages/styled/types/base.d.ts @@ -23,7 +23,7 @@ export interface FilteringStyledOptions< target?: string } -export interface StyledOptions { +export interface StyledOptions> { label?: string shouldForwardProp?(propName: PropertyKey): boolean target?: string From 29ca4375fa34937e7e749f206e52eb69c10ad1d4 Mon Sep 17 00:00:00 2001 From: Anton Golub Date: Tue, 6 Apr 2021 17:17:15 +0300 Subject: [PATCH 02/25] chore(native): let StyledOptions generic argument be optional --- packages/native/types/base.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/native/types/base.d.ts b/packages/native/types/base.d.ts index 182772fb8..b8869d62f 100644 --- a/packages/native/types/base.d.ts +++ b/packages/native/types/base.d.ts @@ -64,7 +64,7 @@ export interface FilteringStyledOptions< shouldForwardProp?(propName: PropertyKey): propName is ForwardedProps } -export interface StyledOptions { +export interface StyledOptions> { shouldForwardProp?(propName: PropertyKey): boolean } From 107e0175319c1b1b94e4aae8592bfd2ad6c5cbf1 Mon Sep 17 00:00:00 2001 From: Anton Golub Date: Wed, 7 Apr 2021 14:55:48 +0300 Subject: [PATCH 03/25] test(types): add tests for StyledOptions iface --- packages/native/types/tests.tsx | 14 +++++++++++++- packages/styled/types/tests.tsx | 20 +++++++++++++++++++- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/packages/native/types/tests.tsx b/packages/native/types/tests.tsx index 50ba21da7..f4b17c494 100644 --- a/packages/native/types/tests.tsx +++ b/packages/native/types/tests.tsx @@ -7,7 +7,7 @@ import { TextStyle, View } from 'react-native' -import styled, { css, ReactNativeStyle } from '@emotion/native' +import styled, { css, ReactNativeStyle, StyledOptions } from '@emotion/native' declare module '@emotion/react' { // tslint:disable-next-line: strict-export-declare-modifiers @@ -167,3 +167,15 @@ export const ImageFullWidthContained = styled.Image` ; ; } + +const styledOpts: StyledOptions = { + shouldForwardProp: p => true +} + +const styledOptsParameterized: StyledOptions> = { + shouldForwardProp: p => true +} + +const styledOptsBroken: StyledOptions = { + shouldForwardProp: (p1, p2) => true // $ExpectError +} diff --git a/packages/styled/types/tests.tsx b/packages/styled/types/tests.tsx index 45d88699f..04c0430a1 100644 --- a/packages/styled/types/tests.tsx +++ b/packages/styled/types/tests.tsx @@ -1,5 +1,5 @@ import * as React from 'react' -import styled from '@emotion/styled' +import styled, { StyledOptions } from '@emotion/styled' // This file uses the same Theme declaration from tests-base.tsx @@ -217,3 +217,21 @@ const Input5 = styled.input` // $ExpectError ; } + +const styledOpts: StyledOptions = { + label: 'foo', + target: 'bar', + shouldForwardProp: p => true +} + +const styledOptsParameterized: StyledOptions> = { + label: 'foo', + target: 'bar', + shouldForwardProp: p => true +} + +const styledOptsBroken: StyledOptions = { + label: 1, // $ExpectError + target: null, // $ExpectError + shouldForwardProp: (p1, p2) => true // $ExpectError +} From d163c006676676679c27d15256faa0905090f134 Mon Sep 17 00:00:00 2001 From: Anton Golub Date: Wed, 7 Apr 2021 20:27:30 +0300 Subject: [PATCH 04/25] feat(types): add keys assertion for StyledOptions generic --- packages/native/types/base.d.ts | 6 ++++-- packages/native/types/tests.tsx | 23 +++++++++++--------- packages/styled/types/base.d.ts | 6 ++++-- packages/styled/types/tests.tsx | 37 ++++++++++++++++++++------------- 4 files changed, 43 insertions(+), 29 deletions(-) diff --git a/packages/native/types/base.d.ts b/packages/native/types/base.d.ts index b8869d62f..3b84c7995 100644 --- a/packages/native/types/base.d.ts +++ b/packages/native/types/base.d.ts @@ -64,8 +64,10 @@ export interface FilteringStyledOptions< shouldForwardProp?(propName: PropertyKey): propName is ForwardedProps } -export interface StyledOptions> { - shouldForwardProp?(propName: PropertyKey): boolean +export interface StyledOptions { + shouldForwardProp?( + propName: Props extends null ? PropertyKey : keyof Props + ): boolean } /** diff --git a/packages/native/types/tests.tsx b/packages/native/types/tests.tsx index f4b17c494..95333f0f6 100644 --- a/packages/native/types/tests.tsx +++ b/packages/native/types/tests.tsx @@ -168,14 +168,17 @@ export const ImageFullWidthContained = styled.Image` ; } -const styledOpts: StyledOptions = { - shouldForwardProp: p => true -} - -const styledOptsParameterized: StyledOptions> = { - shouldForwardProp: p => true -} - -const styledOptsBroken: StyledOptions = { - shouldForwardProp: (p1, p2) => true // $ExpectError +{ + const styledOpts: StyledOptions = { + shouldForwardProp: p => true + } + const styledOptsParameterized: StyledOptions<{ foo: string }> = { + shouldForwardProp: (p: 'foo') => true + } + const styledOptsParameterizedBroken: StyledOptions<{ foo: string }> = { + shouldForwardProp: (p: 'bar') => true // $ExpectError + } + const styledOptsBroken: StyledOptions = { + shouldForwardProp: (p1, p2) => true // $ExpectError + } } diff --git a/packages/styled/types/base.d.ts b/packages/styled/types/base.d.ts index c40430836..c69f4e5e8 100644 --- a/packages/styled/types/base.d.ts +++ b/packages/styled/types/base.d.ts @@ -23,9 +23,11 @@ export interface FilteringStyledOptions< target?: string } -export interface StyledOptions> { +export interface StyledOptions { label?: string - shouldForwardProp?(propName: PropertyKey): boolean + shouldForwardProp?( + propName: Props extends null ? PropertyKey : keyof Props + ): boolean target?: string } diff --git a/packages/styled/types/tests.tsx b/packages/styled/types/tests.tsx index 04c0430a1..38540c0d7 100644 --- a/packages/styled/types/tests.tsx +++ b/packages/styled/types/tests.tsx @@ -218,20 +218,27 @@ const Input5 = styled.input` ; } -const styledOpts: StyledOptions = { - label: 'foo', - target: 'bar', - shouldForwardProp: p => true -} - -const styledOptsParameterized: StyledOptions> = { - label: 'foo', - target: 'bar', - shouldForwardProp: p => true -} +{ + type StyledOptsParameterized = StyledOptions<{ a: string; b: number }> -const styledOptsBroken: StyledOptions = { - label: 1, // $ExpectError - target: null, // $ExpectError - shouldForwardProp: (p1, p2) => true // $ExpectError + const styledOpts0: StyledOptions = { + label: 'foo', + target: 'bar', + shouldForwardProp: p => true + } + const styledOpts1: StyledOptsParameterized = { + label: 'foo', + target: 'bar', + shouldForwardProp: (p: 'a' | string) => true + } + const styledOptsBroken0: StyledOptsParameterized = { + label: 'foo', + target: 'bar', + shouldForwardProp: (p: 'c' | number) => true // $ExpectError + } + const styledOptsBroken1: StyledOptions = { + label: 1, // $ExpectError + target: null, // $ExpectError + shouldForwardProp: (p1, p2) => true // $ExpectError + } } From 4c5b17ede4983b8e8fbb53e6acc3dabab6c67e5d Mon Sep 17 00:00:00 2001 From: Anton Golub Date: Fri, 9 Apr 2021 21:27:03 +0300 Subject: [PATCH 05/25] fix(styled): add StyledOptions type to CreateStyledComponent call signature fixes https://github.com/emotion-js/emotion/pull/2333#discussion_r609965699 --- packages/native/types/base.d.ts | 16 +++++++++++----- packages/styled/types/base.d.ts | 22 ++++++++++++++++------ packages/styled/types/tests.tsx | 12 ++++++++++++ 3 files changed, 39 insertions(+), 11 deletions(-) diff --git a/packages/native/types/base.d.ts b/packages/native/types/base.d.ts index 3b84c7995..c650637f6 100644 --- a/packages/native/types/base.d.ts +++ b/packages/native/types/base.d.ts @@ -105,11 +105,17 @@ export interface CreateStyledComponent< * @typeparam AdditionalProps Additional props to add to your styled component */ ( - ...styles: ArrayInterpolation< - ComponentProps & - SpecificComponentProps & - AdditionalProps & { theme: Theme }, - StyleType + ...styles: Array< + | StyledOptions< + ComponentProps & + SpecificComponentProps & + AdditionalProps & { theme: Theme } + > + | Interpolation< + ComponentProps & + SpecificComponentProps & + AdditionalProps & { theme: Theme } + > > ): StyledComponent< ComponentProps & AdditionalProps, diff --git a/packages/styled/types/base.d.ts b/packages/styled/types/base.d.ts index c69f4e5e8..e89c7b8ba 100644 --- a/packages/styled/types/base.d.ts +++ b/packages/styled/types/base.d.ts @@ -2,7 +2,11 @@ // TypeScript Version: 3.2 import * as React from 'react' -import { ComponentSelector, Interpolation } from '@emotion/serialize' +import { + ComponentSelector, + Interpolation, + InterpolationPrimitive +} from '@emotion/serialize' import { PropsOf, DistributiveOmit, Theme } from '@emotion/react' export { @@ -71,11 +75,17 @@ export interface CreateStyledComponent< */ ( ...styles: Array< - Interpolation< - ComponentProps & - SpecificComponentProps & - AdditionalProps & { theme: Theme } - > + // tslint:disable-next-line no-null-undefined-union + | StyledOptions< + ComponentProps & + SpecificComponentProps & + AdditionalProps & { theme: Theme } + > + | Interpolation< + ComponentProps & + SpecificComponentProps & + AdditionalProps & { theme: Theme } + > > ): StyledComponent< ComponentProps & AdditionalProps, diff --git a/packages/styled/types/tests.tsx b/packages/styled/types/tests.tsx index 38540c0d7..bbdb563c9 100644 --- a/packages/styled/types/tests.tsx +++ b/packages/styled/types/tests.tsx @@ -241,4 +241,16 @@ const Input5 = styled.input` target: null, // $ExpectError shouldForwardProp: (p1, p2) => true // $ExpectError } + + interface Props { + foo: boolean + } + const options: StyledOptions = { + label: 'foo', + target: 'bar', + shouldForwardProp: p => true + } + const test1 = styled.div({ color: 'red' }, options) + const test2 = styled.div({ color: 'red' }, options) + const test3 = styled('div', options)({ color: 'red' }) } From 696213b53a5a5e6a348f444fa56174328b04ffb5 Mon Sep 17 00:00:00 2001 From: Anton Golub Date: Sun, 18 Apr 2021 13:45:57 +0300 Subject: [PATCH 06/25] test(styled): check type StyledOpts for composite component --- packages/native/types/base.d.ts | 16 +++++----------- packages/styled/types/tests.tsx | 3 +++ 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/packages/native/types/base.d.ts b/packages/native/types/base.d.ts index c650637f6..3b84c7995 100644 --- a/packages/native/types/base.d.ts +++ b/packages/native/types/base.d.ts @@ -105,17 +105,11 @@ export interface CreateStyledComponent< * @typeparam AdditionalProps Additional props to add to your styled component */ ( - ...styles: Array< - | StyledOptions< - ComponentProps & - SpecificComponentProps & - AdditionalProps & { theme: Theme } - > - | Interpolation< - ComponentProps & - SpecificComponentProps & - AdditionalProps & { theme: Theme } - > + ...styles: ArrayInterpolation< + ComponentProps & + SpecificComponentProps & + AdditionalProps & { theme: Theme }, + StyleType > ): StyledComponent< ComponentProps & AdditionalProps, diff --git a/packages/styled/types/tests.tsx b/packages/styled/types/tests.tsx index bbdb563c9..6eb8ec51d 100644 --- a/packages/styled/types/tests.tsx +++ b/packages/styled/types/tests.tsx @@ -253,4 +253,7 @@ const Input5 = styled.input` const test1 = styled.div({ color: 'red' }, options) const test2 = styled.div({ color: 'red' }, options) const test3 = styled('div', options)({ color: 'red' }) + const test4 = styled(() =>
, options)({ + color: 'red' + }) } From fae2dab31500962e58142bd1185da61b7f7a46db Mon Sep 17 00:00:00 2001 From: Anton Golub Date: Mon, 19 Apr 2021 09:44:05 +0300 Subject: [PATCH 07/25] test(styled): revert erroneous changes --- packages/styled/types/base.d.ts | 16 +++++----------- packages/styled/types/tests.tsx | 9 +++++---- 2 files changed, 10 insertions(+), 15 deletions(-) diff --git a/packages/styled/types/base.d.ts b/packages/styled/types/base.d.ts index e89c7b8ba..c846d25aa 100644 --- a/packages/styled/types/base.d.ts +++ b/packages/styled/types/base.d.ts @@ -75,17 +75,11 @@ export interface CreateStyledComponent< */ ( ...styles: Array< - // tslint:disable-next-line no-null-undefined-union - | StyledOptions< - ComponentProps & - SpecificComponentProps & - AdditionalProps & { theme: Theme } - > - | Interpolation< - ComponentProps & - SpecificComponentProps & - AdditionalProps & { theme: Theme } - > + Interpolation< + ComponentProps & + SpecificComponentProps & + AdditionalProps & { theme: Theme } + > > ): StyledComponent< ComponentProps & AdditionalProps, diff --git a/packages/styled/types/tests.tsx b/packages/styled/types/tests.tsx index 6eb8ec51d..6f9a5e6f4 100644 --- a/packages/styled/types/tests.tsx +++ b/packages/styled/types/tests.tsx @@ -250,10 +250,11 @@ const Input5 = styled.input` target: 'bar', shouldForwardProp: p => true } - const test1 = styled.div({ color: 'red' }, options) - const test2 = styled.div({ color: 'red' }, options) - const test3 = styled('div', options)({ color: 'red' }) - const test4 = styled(() =>
, options)({ + + const test1 = styled('div', options)({ color: 'red' }) + const test2 = styled('div', options)({ color: 'red' }) + const test3 = styled(() =>
, options)({ color: 'red' }) + const test4 = styled(() =>
, options)({ color: 'red' }) } From 2238e9e895be4498bdc32d77c7ccd57ecc482c58 Mon Sep 17 00:00:00 2001 From: Anton Golub Date: Mon, 19 Apr 2021 09:54:16 +0300 Subject: [PATCH 08/25] test(styled): clarify StyledOptsBroken test case --- packages/styled/types/tests.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/styled/types/tests.tsx b/packages/styled/types/tests.tsx index 6f9a5e6f4..d4380ec60 100644 --- a/packages/styled/types/tests.tsx +++ b/packages/styled/types/tests.tsx @@ -229,12 +229,13 @@ const Input5 = styled.input` const styledOpts1: StyledOptsParameterized = { label: 'foo', target: 'bar', - shouldForwardProp: (p: 'a' | string) => true + shouldForwardProp: (p: 'a' | 'b') => true } + const styledOptsBroken0: StyledOptsParameterized = { label: 'foo', target: 'bar', - shouldForwardProp: (p: 'c' | number) => true // $ExpectError + shouldForwardProp: (p: 'c') => true // $ExpectError } const styledOptsBroken1: StyledOptions = { label: 1, // $ExpectError From d889b0ec087c7d568d87425e28c416dbc190278e Mon Sep 17 00:00:00 2001 From: Anton Golub Date: Wed, 12 Jan 2022 23:00:47 +0300 Subject: [PATCH 09/25] test: refactor `styledOptions` generics tests --- packages/styled/types/tests.tsx | 56 +++++++++++++-------------------- 1 file changed, 21 insertions(+), 35 deletions(-) diff --git a/packages/styled/types/tests.tsx b/packages/styled/types/tests.tsx index d4380ec60..f41359e08 100644 --- a/packages/styled/types/tests.tsx +++ b/packages/styled/types/tests.tsx @@ -219,43 +219,29 @@ const Input5 = styled.input` } { - type StyledOptsParameterized = StyledOptions<{ a: string; b: number }> + const fc: React.FC<{ foo: string }> = props =>
- const styledOpts0: StyledOptions = { - label: 'foo', - target: 'bar', - shouldForwardProp: p => true - } - const styledOpts1: StyledOptsParameterized = { - label: 'foo', - target: 'bar', - shouldForwardProp: (p: 'a' | 'b') => true - } + styled(fc, { shouldForwardProp: (prop: 'foo') => true })({}) - const styledOptsBroken0: StyledOptsParameterized = { - label: 'foo', - target: 'bar', - shouldForwardProp: (p: 'c') => true // $ExpectError - } - const styledOptsBroken1: StyledOptions = { - label: 1, // $ExpectError - target: null, // $ExpectError - shouldForwardProp: (p1, p2) => true // $ExpectError - } + styled(fc, { shouldForwardProp: (prop: 'bar') => true })({}) // $ExpectError - interface Props { - foo: boolean - } - const options: StyledOptions = { - label: 'foo', - target: 'bar', - shouldForwardProp: p => true - } + styled>>(fc, { + shouldForwardProp: (prop: 'foo') => true + })({}) + + styled>>(fc, { + shouldForwardProp: (prop: 'bar') => true + })({}) // $ExpectError + + styled('div', { shouldForwardProp: (prop: 'color') => true })({}) + + styled('div', { shouldForwardProp: (prop: 'foo') => true })({}) // $ExpectError + + styled('div', { + shouldForwardProp: (prop: 'color') => true + })({}) - const test1 = styled('div', options)({ color: 'red' }) - const test2 = styled('div', options)({ color: 'red' }) - const test3 = styled(() =>
, options)({ color: 'red' }) - const test4 = styled(() =>
, options)({ - color: 'red' - }) + styled('div', { + shouldForwardProp: (prop: 'foo') => true + })({}) // $ExpectError } From 0fa6ee48811da990e5f0e3fccf0af18e0e96c248 Mon Sep 17 00:00:00 2001 From: Anton Golub Date: Wed, 12 Jan 2022 23:28:08 +0300 Subject: [PATCH 10/25] test: add more tests for StyledOptions --- packages/styled/types/tests.tsx | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/packages/styled/types/tests.tsx b/packages/styled/types/tests.tsx index f41359e08..7b3667c90 100644 --- a/packages/styled/types/tests.tsx +++ b/packages/styled/types/tests.tsx @@ -223,25 +223,43 @@ const Input5 = styled.input` styled(fc, { shouldForwardProp: (prop: 'foo') => true })({}) - styled(fc, { shouldForwardProp: (prop: 'bar') => true })({}) // $ExpectError + styled(fc, { shouldForwardProp: (prop: string) => true })({}) + + // $ExpectError + styled(fc, { shouldForwardProp: (prop: 'bar') => true })({}) + + const shouldForwardProp1: StyledOptions['shouldForwardProp'] = ( + prop: 'unknown' + ) => true + styled(fc, { shouldForwardProp: shouldForwardProp1 })({}) + + const shouldForwardProp2 = (prop: 'foo') => true + styled(fc, { shouldForwardProp: shouldForwardProp2 })({}) + + const shouldForwardProp3 = (prop: 'unknown') => true + // $ExpectError + styled(fc, { shouldForwardProp: shouldForwardProp3 })({}) styled>>(fc, { shouldForwardProp: (prop: 'foo') => true })({}) + // $ExpectError styled>>(fc, { shouldForwardProp: (prop: 'bar') => true - })({}) // $ExpectError + })({}) // eslint-disable-line styled('div', { shouldForwardProp: (prop: 'color') => true })({}) - styled('div', { shouldForwardProp: (prop: 'foo') => true })({}) // $ExpectError + // $ExpectError + styled('div', { shouldForwardProp: (prop: 'foo') => true })({}) styled('div', { shouldForwardProp: (prop: 'color') => true })({}) + // $ExpectError styled('div', { shouldForwardProp: (prop: 'foo') => true - })({}) // $ExpectError + })({}) // eslint-disable-line } From ebfbd9a9f57840a2eb74090b5bc8ae904fee026d Mon Sep 17 00:00:00 2001 From: Anton Golub Date: Wed, 12 Jan 2022 23:44:02 +0300 Subject: [PATCH 11/25] test: linting --- packages/styled/types/tests.tsx | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/packages/styled/types/tests.tsx b/packages/styled/types/tests.tsx index 7b3667c90..58437dc58 100644 --- a/packages/styled/types/tests.tsx +++ b/packages/styled/types/tests.tsx @@ -245,9 +245,7 @@ const Input5 = styled.input` })({}) // $ExpectError - styled>>(fc, { - shouldForwardProp: (prop: 'bar') => true - })({}) // eslint-disable-line + styled>>(fc, { shouldForwardProp: (prop: 'bar') => true })({}) // prettier-ignore styled('div', { shouldForwardProp: (prop: 'color') => true })({}) @@ -259,7 +257,5 @@ const Input5 = styled.input` })({}) // $ExpectError - styled('div', { - shouldForwardProp: (prop: 'foo') => true - })({}) // eslint-disable-line + styled('div', { shouldForwardProp: (prop: 'foo') => true })({}) // prettier-ignore } From 9e783452273c1447a3ae8e7d8a5e9c7c2fad93fc Mon Sep 17 00:00:00 2001 From: Anton Golub Date: Wed, 12 Jan 2022 23:55:05 +0300 Subject: [PATCH 12/25] test: tweak ups --- packages/styled/types/tests.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/styled/types/tests.tsx b/packages/styled/types/tests.tsx index 58437dc58..c6713561d 100644 --- a/packages/styled/types/tests.tsx +++ b/packages/styled/types/tests.tsx @@ -228,12 +228,12 @@ const Input5 = styled.input` // $ExpectError styled(fc, { shouldForwardProp: (prop: 'bar') => true })({}) - const shouldForwardProp1: StyledOptions['shouldForwardProp'] = ( - prop: 'unknown' - ) => true + const shouldForwardProp1 = (prop: 'foo') => true styled(fc, { shouldForwardProp: shouldForwardProp1 })({}) - const shouldForwardProp2 = (prop: 'foo') => true + const shouldForwardProp2: StyledOptions['shouldForwardProp'] = ( + prop: 'unknown' + ) => true styled(fc, { shouldForwardProp: shouldForwardProp2 })({}) const shouldForwardProp3 = (prop: 'unknown') => true From 894aa3be7be0c2d992685472099f956075cf8737 Mon Sep 17 00:00:00 2001 From: Anton Golub Date: Fri, 14 Jan 2022 19:07:59 +0300 Subject: [PATCH 13/25] feat: expose FilteringStyledOptions --- packages/native/types/base.d.ts | 2 +- packages/styled/types/base.d.ts | 2 +- packages/styled/types/index.d.ts | 1 + packages/styled/types/tests.tsx | 44 ++++++++++++++++++++++++-------- 4 files changed, 37 insertions(+), 12 deletions(-) diff --git a/packages/native/types/base.d.ts b/packages/native/types/base.d.ts index dc34579f1..3de80df19 100644 --- a/packages/native/types/base.d.ts +++ b/packages/native/types/base.d.ts @@ -60,7 +60,7 @@ export type Interpolation< /** Same as StyledOptions but shouldForwardProp must be a type guard */ export interface FilteringStyledOptions< - Props, + Props = Record, ForwardedProps extends keyof Props = keyof Props > { shouldForwardProp?(propName: PropertyKey): propName is ForwardedProps diff --git a/packages/styled/types/base.d.ts b/packages/styled/types/base.d.ts index 905a75ec1..4c9721107 100644 --- a/packages/styled/types/base.d.ts +++ b/packages/styled/types/base.d.ts @@ -19,7 +19,7 @@ export { ComponentSelector, Interpolation } /** Same as StyledOptions but shouldForwardProp must be a type guard */ export interface FilteringStyledOptions< - Props, + Props = Record, ForwardedProps extends keyof Props = keyof Props > { label?: string diff --git a/packages/styled/types/index.d.ts b/packages/styled/types/index.d.ts index 286a2d176..883a79ea0 100644 --- a/packages/styled/types/index.d.ts +++ b/packages/styled/types/index.d.ts @@ -12,6 +12,7 @@ export { Interpolation, StyledComponent, StyledOptions, + FilteringStyledOptions, CreateStyledComponent } from './base' diff --git a/packages/styled/types/tests.tsx b/packages/styled/types/tests.tsx index c6713561d..d4bbb1fec 100644 --- a/packages/styled/types/tests.tsx +++ b/packages/styled/types/tests.tsx @@ -1,5 +1,5 @@ import * as React from 'react' -import styled, { StyledOptions } from '@emotion/styled' +import styled, { StyledOptions, FilteringStyledOptions } from '@emotion/styled' // This file uses the same Theme declaration from tests-base.tsx @@ -219,6 +219,8 @@ const Input5 = styled.input` } { + // Props forwarding through StyledOptions and FilteringStyledOptions + const fc: React.FC<{ foo: string }> = props =>
styled(fc, { shouldForwardProp: (prop: 'foo') => true })({}) @@ -240,22 +242,44 @@ const Input5 = styled.input` // $ExpectError styled(fc, { shouldForwardProp: shouldForwardProp3 })({}) - styled>>(fc, { - shouldForwardProp: (prop: 'foo') => true - })({}) + // $ExpectError + const shouldForwardProp4: StyledOptions<{ + foo: string + }>['shouldForwardProp'] = (prop: 'unknown') => true + + const shouldForwardProp5 = (prop: 'foo'): prop is 'foo' => true + styled(fc, { shouldForwardProp: shouldForwardProp5 })({}) + + const shouldForwardProp6: FilteringStyledOptions['shouldForwardProp'] = ( + prop: 'foo' + ): prop is 'foo' => true + + const shouldForwardProp7: FilteringStyledOptions<{ + foo: string + }>['shouldForwardProp'] = (prop: 'foo'): prop is 'foo' => true // $ExpectError - styled>>(fc, { shouldForwardProp: (prop: 'bar') => true })({}) // prettier-ignore + const shouldForwardProp8: FilteringStyledOptions<{ + foo: string + }>['shouldForwardProp'] = (prop: 'unknown'): prop is 'unknown' => true - styled('div', { shouldForwardProp: (prop: 'color') => true })({}) + const shouldForwardProp9: FilteringStyledOptions< + { foo: string; bar: string }, + 'foo' + >['shouldForwardProp'] = (prop: 'foo'): prop is 'foo' => true // $ExpectError - styled('div', { shouldForwardProp: (prop: 'foo') => true })({}) + const shouldForwardProp10: FilteringStyledOptions< + { foo: string; bar: string }, + 'foo' + >['shouldForwardProp'] = (prop: 'bar'): prop is 'bar' => true - styled('div', { - shouldForwardProp: (prop: 'color') => true + styled('div', { shouldForwardProp: (prop: 'color') => true })({}) + + styled('div', { + shouldForwardProp: (prop: 'color'): prop is 'color' => true })({}) // $ExpectError - styled('div', { shouldForwardProp: (prop: 'foo') => true })({}) // prettier-ignore + styled('div', { shouldForwardProp: (prop: 'foo') => true })({}) } From 27b4f2da0ff81b9a14ad75db8f7fa28bd54bc1bf Mon Sep 17 00:00:00 2001 From: Anton Golub Date: Fri, 25 Feb 2022 19:33:24 +0300 Subject: [PATCH 14/25] fix: expost `FilteringStyledOptions` from native, tweak up some tests, add some comments --- packages/native/types/base.d.ts | 5 ++++- packages/native/types/index.d.ts | 1 + packages/native/types/tests.tsx | 29 ++++++++++++++++------------- packages/styled/types/base.d.ts | 5 ++++- packages/styled/types/tests.tsx | 4 ++-- 5 files changed, 27 insertions(+), 17 deletions(-) diff --git a/packages/native/types/base.d.ts b/packages/native/types/base.d.ts index 3de80df19..f5bf6e683 100644 --- a/packages/native/types/base.d.ts +++ b/packages/native/types/base.d.ts @@ -58,7 +58,10 @@ export type Interpolation< | ArrayInterpolation | FunctionInterpolation -/** Same as StyledOptions but shouldForwardProp must be a type guard */ +/** + * Same as StyledOptions but shouldForwardProp must be a type guard (https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates). + * Practical sense: you can define and reuse atomic `shouldForwardProp` filters that are strictly bound with some `ForwardedProps` type. + */ export interface FilteringStyledOptions< Props = Record, ForwardedProps extends keyof Props = keyof Props diff --git a/packages/native/types/index.d.ts b/packages/native/types/index.d.ts index 4e6bb9a12..975f2a7bf 100644 --- a/packages/native/types/index.d.ts +++ b/packages/native/types/index.d.ts @@ -18,6 +18,7 @@ export { ArrayInterpolation, CreateStyledComponent, CSSInterpolation, + FilteringStyledOptions, FunctionInterpolation, Interpolation, InterpolationPrimitive, diff --git a/packages/native/types/tests.tsx b/packages/native/types/tests.tsx index b855213e6..c80814cea 100644 --- a/packages/native/types/tests.tsx +++ b/packages/native/types/tests.tsx @@ -7,7 +7,12 @@ import { TextStyle, View } from 'react-native' -import styled, { css, ReactNativeStyle, StyledOptions } from '@emotion/native' +import styled, { + css, + ReactNativeStyle, + StyledOptions, + FilteringStyledOptions +} from '@emotion/native' declare module '@emotion/react' { // tslint:disable-next-line: strict-export-declare-modifiers @@ -168,16 +173,14 @@ export const ImageFullWidthContained = styled.Image` } { - const styledOpts: StyledOptions = { - shouldForwardProp: p => true - } - const styledOptsParameterized: StyledOptions<{ foo: string }> = { - shouldForwardProp: (p: 'foo') => true - } - const styledOptsParameterizedBroken: StyledOptions<{ foo: string }> = { - shouldForwardProp: (p: 'bar') => true // $ExpectError - } - const styledOptsBroken: StyledOptions = { - shouldForwardProp: (p1, p2) => true // $ExpectError - } + // Props forwarding through StyledOptions and FilteringStyledOptions + + styled(View, { shouldForwardProp: (prop: 'testID') => true })({}) + + styled(View, { + shouldForwardProp: (prop: 'testID'): prop is 'testID' => true + })({}) + + // $ExpectError + styled(View, { shouldForwardProp: (prop: 'foo') => true })({}) } diff --git a/packages/styled/types/base.d.ts b/packages/styled/types/base.d.ts index 4c9721107..007013f8b 100644 --- a/packages/styled/types/base.d.ts +++ b/packages/styled/types/base.d.ts @@ -17,7 +17,10 @@ export { export { ComponentSelector, Interpolation } -/** Same as StyledOptions but shouldForwardProp must be a type guard */ +/** + * Same as StyledOptions but shouldForwardProp must be a type guard (https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates). + * Practical sense: you can define and reuse atomic `shouldForwardProp` filters that are strictly bound with some `ForwardedProps` type. + */ export interface FilteringStyledOptions< Props = Record, ForwardedProps extends keyof Props = keyof Props diff --git a/packages/styled/types/tests.tsx b/packages/styled/types/tests.tsx index d4bbb1fec..6e9cd4951 100644 --- a/packages/styled/types/tests.tsx +++ b/packages/styled/types/tests.tsx @@ -266,13 +266,13 @@ const Input5 = styled.input` const shouldForwardProp9: FilteringStyledOptions< { foo: string; bar: string }, 'foo' - >['shouldForwardProp'] = (prop: 'foo'): prop is 'foo' => true + >['shouldForwardProp'] = (prop: 'foo' | 'bar'): prop is 'foo' => true // $ExpectError const shouldForwardProp10: FilteringStyledOptions< { foo: string; bar: string }, 'foo' - >['shouldForwardProp'] = (prop: 'bar'): prop is 'bar' => true + >['shouldForwardProp'] = (prop: 'foo' | 'bar'): prop is 'bar' => true styled('div', { shouldForwardProp: (prop: 'color') => true })({}) From d3092bb50f0aa1dafda7d071a3abd1117b2a1de9 Mon Sep 17 00:00:00 2001 From: Anton Golub Date: Tue, 8 Mar 2022 14:56:00 +0300 Subject: [PATCH 15/25] chore: use consistent default props type for both StyledOptions and FilteringStyledOptions --- packages/native/types/base.d.ts | 6 ++---- packages/styled/types/base.d.ts | 6 ++---- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/packages/native/types/base.d.ts b/packages/native/types/base.d.ts index f5bf6e683..dd25fde4b 100644 --- a/packages/native/types/base.d.ts +++ b/packages/native/types/base.d.ts @@ -69,10 +69,8 @@ export interface FilteringStyledOptions< shouldForwardProp?(propName: PropertyKey): propName is ForwardedProps } -export interface StyledOptions { - shouldForwardProp?( - propName: Props extends null ? PropertyKey : keyof Props - ): boolean +export interface StyledOptions> { + shouldForwardProp?(propName: keyof Props): boolean } /** diff --git a/packages/styled/types/base.d.ts b/packages/styled/types/base.d.ts index 007013f8b..12f0b621d 100644 --- a/packages/styled/types/base.d.ts +++ b/packages/styled/types/base.d.ts @@ -30,11 +30,9 @@ export interface FilteringStyledOptions< target?: string } -export interface StyledOptions { +export interface StyledOptions> { label?: string - shouldForwardProp?( - propName: Props extends null ? PropertyKey : keyof Props - ): boolean + shouldForwardProp?(propName: keyof Props): boolean target?: string } From 4104c2abcc992cd8c0989d2fc2b639fa032af216 Mon Sep 17 00:00:00 2001 From: Anton Golub Date: Wed, 9 Mar 2022 12:27:27 +0300 Subject: [PATCH 16/25] chore: snap #3 --- packages/native/types/tsconfig.json | 4 ++++ packages/styled/types/tsconfig.json | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/packages/native/types/tsconfig.json b/packages/native/types/tsconfig.json index 12a464ad1..72502a70a 100644 --- a/packages/native/types/tsconfig.json +++ b/packages/native/types/tsconfig.json @@ -6,6 +6,10 @@ "lib": ["es6", "dom"], "module": "commonjs", "noEmit": true, + "noImplicitAny": true, + "noImplicitThis": true, + "strictNullChecks": true, + "strictFunctionTypes": true, "strict": true, "target": "es5", "typeRoots": ["../"], diff --git a/packages/styled/types/tsconfig.json b/packages/styled/types/tsconfig.json index 47e662ca7..3bd01fbe7 100644 --- a/packages/styled/types/tsconfig.json +++ b/packages/styled/types/tsconfig.json @@ -7,6 +7,10 @@ "lib": ["es6", "dom"], "module": "commonjs", "noEmit": true, + "noImplicitAny": true, + "noImplicitThis": true, + "strictNullChecks": true, + "strictFunctionTypes": true, "strict": true, "target": "es5", "typeRoots": ["../"], From 5595c8d82a94e35c25fd2ea40438f7336e28a62f Mon Sep 17 00:00:00 2001 From: Sam Magura Date: Sat, 21 May 2022 10:28:22 -0400 Subject: [PATCH 17/25] styled.shouldForwardProp: require prop to be a string --- packages/is-prop-valid/types/index.d.ts | 2 +- packages/native/types/base.d.ts | 12 +++++++----- packages/styled/types/base.d.ts | 15 +++++++++------ 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/packages/is-prop-valid/types/index.d.ts b/packages/is-prop-valid/types/index.d.ts index 2ca137567..e7d00bfdb 100644 --- a/packages/is-prop-valid/types/index.d.ts +++ b/packages/is-prop-valid/types/index.d.ts @@ -1,5 +1,5 @@ // Definitions by: Junyoung Clare Jang // TypeScript Version: 2.1 -declare function isPropValid(string: PropertyKey): boolean +declare function isPropValid(prop: string): boolean export default isPropValid diff --git a/packages/native/types/base.d.ts b/packages/native/types/base.d.ts index 82aae23be..2afa5f427 100644 --- a/packages/native/types/base.d.ts +++ b/packages/native/types/base.d.ts @@ -61,13 +61,13 @@ export type Interpolation< /** Same as StyledOptions but shouldForwardProp must be a type guard */ export interface FilteringStyledOptions< Props, - ForwardedProps extends keyof Props = keyof Props + ForwardedProps extends keyof Props & string = keyof Props & string > { - shouldForwardProp?(propName: PropertyKey): propName is ForwardedProps + shouldForwardProp?(propName: string): propName is ForwardedProps } export interface StyledOptions { - shouldForwardProp?(propName: PropertyKey): boolean + shouldForwardProp?(propName: string): boolean } /** @@ -146,7 +146,8 @@ export interface CreateStyledComponent< export interface CreateStyled { < C extends React.ComponentClass>, - ForwardedProps extends keyof React.ComponentProps = keyof React.ComponentProps + ForwardedProps extends keyof React.ComponentProps & + string = keyof React.ComponentProps & string >( component: C, options: FilteringStyledOptions, ForwardedProps> @@ -175,7 +176,8 @@ export interface CreateStyled { < C extends React.ComponentType>, - ForwardedProps extends keyof React.ComponentProps = keyof React.ComponentProps + ForwardedProps extends keyof React.ComponentProps & + string = keyof React.ComponentProps & string >( component: C, options: FilteringStyledOptions, ForwardedProps> diff --git a/packages/styled/types/base.d.ts b/packages/styled/types/base.d.ts index c39200c75..4383b0caf 100644 --- a/packages/styled/types/base.d.ts +++ b/packages/styled/types/base.d.ts @@ -16,16 +16,16 @@ export { ComponentSelector, Interpolation } /** Same as StyledOptions but shouldForwardProp must be a type guard */ export interface FilteringStyledOptions< Props, - ForwardedProps extends keyof Props = keyof Props + ForwardedProps extends keyof Props & string = keyof Props & string > { label?: string - shouldForwardProp?(propName: PropertyKey): propName is ForwardedProps + shouldForwardProp?(propName: string): propName is ForwardedProps target?: string } export interface StyledOptions { label?: string - shouldForwardProp?(propName: PropertyKey): boolean + shouldForwardProp?(propName: string): boolean target?: string } @@ -118,7 +118,8 @@ export interface CreateStyledComponent< export interface CreateStyled { < C extends React.ComponentClass>, - ForwardedProps extends keyof React.ComponentProps = keyof React.ComponentProps + ForwardedProps extends keyof React.ComponentProps & + string = keyof React.ComponentProps & string >( component: C, options: FilteringStyledOptions, ForwardedProps> @@ -147,7 +148,8 @@ export interface CreateStyled { < C extends React.ComponentType>, - ForwardedProps extends keyof React.ComponentProps = keyof React.ComponentProps + ForwardedProps extends keyof React.ComponentProps & + string = keyof React.ComponentProps & string >( component: C, options: FilteringStyledOptions, ForwardedProps> @@ -168,7 +170,8 @@ export interface CreateStyled { < Tag extends keyof JSX.IntrinsicElements, - ForwardedProps extends keyof JSX.IntrinsicElements[Tag] = keyof JSX.IntrinsicElements[Tag] + ForwardedProps extends keyof JSX.IntrinsicElements[Tag] & + string = keyof JSX.IntrinsicElements[Tag] & string >( tag: Tag, options: FilteringStyledOptions From 09df01db4b4ef02141f40344e037fc9d1dbb5098 Mon Sep 17 00:00:00 2001 From: Sam Magura Date: Sat, 21 May 2022 10:37:57 -0400 Subject: [PATCH 18/25] Add PropertyKey->string changesets --- .changeset/good-cars-roll.md | 6 ++++++ .changeset/purple-ladybugs-think.md | 5 +++++ 2 files changed, 11 insertions(+) create mode 100644 .changeset/good-cars-roll.md create mode 100644 .changeset/purple-ladybugs-think.md diff --git a/.changeset/good-cars-roll.md b/.changeset/good-cars-roll.md new file mode 100644 index 000000000..4d0921056 --- /dev/null +++ b/.changeset/good-cars-roll.md @@ -0,0 +1,6 @@ +--- +'@emotion/native': patch +'@emotion/styled': patch +--- + +Change the argument of the `shouldForwardProp` option of `styled` from `PropertyKey` to `string` in the TypeScript definitions. diff --git a/.changeset/purple-ladybugs-think.md b/.changeset/purple-ladybugs-think.md new file mode 100644 index 000000000..b30341024 --- /dev/null +++ b/.changeset/purple-ladybugs-think.md @@ -0,0 +1,5 @@ +--- +'@emotion/is-prop-valid': patch +--- + +Change the type of the argument to `isPropValid` from `PropertyKey` to `string` in the TypeScript definitions. From 5f3f5e5db2f444343b02e9bb2efdd6ad8ce4df57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Sat, 21 May 2022 19:01:17 +0200 Subject: [PATCH 19/25] Remove redundant `compilerOptions` --- packages/native/types/tsconfig.json | 4 ---- packages/styled/types/tsconfig.json | 4 ---- 2 files changed, 8 deletions(-) diff --git a/packages/native/types/tsconfig.json b/packages/native/types/tsconfig.json index 72502a70a..12a464ad1 100644 --- a/packages/native/types/tsconfig.json +++ b/packages/native/types/tsconfig.json @@ -6,10 +6,6 @@ "lib": ["es6", "dom"], "module": "commonjs", "noEmit": true, - "noImplicitAny": true, - "noImplicitThis": true, - "strictNullChecks": true, - "strictFunctionTypes": true, "strict": true, "target": "es5", "typeRoots": ["../"], diff --git a/packages/styled/types/tsconfig.json b/packages/styled/types/tsconfig.json index 3bd01fbe7..47e662ca7 100644 --- a/packages/styled/types/tsconfig.json +++ b/packages/styled/types/tsconfig.json @@ -7,10 +7,6 @@ "lib": ["es6", "dom"], "module": "commonjs", "noEmit": true, - "noImplicitAny": true, - "noImplicitThis": true, - "strictNullChecks": true, - "strictFunctionTypes": true, "strict": true, "target": "es5", "typeRoots": ["../"], From da3a461da886e24d4d461c3c427c7cfb3aa940c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Mon, 23 May 2022 00:23:12 +0200 Subject: [PATCH 20/25] make `shouldForwardProp` always contravariant --- packages/native/types/base.d.ts | 4 ++-- packages/styled/types/base.d.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/native/types/base.d.ts b/packages/native/types/base.d.ts index dd25fde4b..dda50948c 100644 --- a/packages/native/types/base.d.ts +++ b/packages/native/types/base.d.ts @@ -66,11 +66,11 @@ export interface FilteringStyledOptions< Props = Record, ForwardedProps extends keyof Props = keyof Props > { - shouldForwardProp?(propName: PropertyKey): propName is ForwardedProps + shouldForwardProp?: (propName: PropertyKey) => propName is ForwardedProps } export interface StyledOptions> { - shouldForwardProp?(propName: keyof Props): boolean + shouldForwardProp?: (propName: keyof Props) => boolean } /** diff --git a/packages/styled/types/base.d.ts b/packages/styled/types/base.d.ts index 12f0b621d..ca473bafc 100644 --- a/packages/styled/types/base.d.ts +++ b/packages/styled/types/base.d.ts @@ -26,13 +26,13 @@ export interface FilteringStyledOptions< ForwardedProps extends keyof Props = keyof Props > { label?: string - shouldForwardProp?(propName: PropertyKey): propName is ForwardedProps + shouldForwardProp?: (propName: PropertyKey) => propName is ForwardedProps target?: string } export interface StyledOptions> { label?: string - shouldForwardProp?(propName: keyof Props): boolean + shouldForwardProp?: (propName: keyof Props) => boolean target?: string } From f360473b77b0de49bdffa9acd8c55e18cfee8b7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Mon, 30 May 2022 17:03:53 +0200 Subject: [PATCH 21/25] Type fixes --- packages/native/types/base.d.ts | 4 ++-- packages/styled/types/base.d.ts | 14 +++++------- packages/styled/types/tests.tsx | 39 ++++++++++++++++++++------------- 3 files changed, 31 insertions(+), 26 deletions(-) diff --git a/packages/native/types/base.d.ts b/packages/native/types/base.d.ts index dda50948c..6b6e11e4a 100644 --- a/packages/native/types/base.d.ts +++ b/packages/native/types/base.d.ts @@ -63,10 +63,10 @@ export type Interpolation< * Practical sense: you can define and reuse atomic `shouldForwardProp` filters that are strictly bound with some `ForwardedProps` type. */ export interface FilteringStyledOptions< - Props = Record, + Props = Record, ForwardedProps extends keyof Props = keyof Props > { - shouldForwardProp?: (propName: PropertyKey) => propName is ForwardedProps + shouldForwardProp?: (propName: keyof Props) => propName is ForwardedProps } export interface StyledOptions> { diff --git a/packages/styled/types/base.d.ts b/packages/styled/types/base.d.ts index ca473bafc..b1905352c 100644 --- a/packages/styled/types/base.d.ts +++ b/packages/styled/types/base.d.ts @@ -2,12 +2,8 @@ // TypeScript Version: 3.2 import * as React from 'react' -import { - ComponentSelector, - Interpolation, - InterpolationPrimitive -} from '@emotion/serialize' -import { PropsOf, DistributiveOmit, Theme } from '@emotion/react' +import { ComponentSelector, Interpolation } from '@emotion/serialize' +import { PropsOf, Theme } from '@emotion/react' export { ArrayInterpolation, @@ -22,15 +18,15 @@ export { ComponentSelector, Interpolation } * Practical sense: you can define and reuse atomic `shouldForwardProp` filters that are strictly bound with some `ForwardedProps` type. */ export interface FilteringStyledOptions< - Props = Record, + Props = Record, ForwardedProps extends keyof Props = keyof Props > { label?: string - shouldForwardProp?: (propName: PropertyKey) => propName is ForwardedProps + shouldForwardProp?: (propName: keyof Props) => propName is ForwardedProps target?: string } -export interface StyledOptions> { +export interface StyledOptions> { label?: string shouldForwardProp?: (propName: keyof Props) => boolean target?: string diff --git a/packages/styled/types/tests.tsx b/packages/styled/types/tests.tsx index 6e9cd4951..266843120 100644 --- a/packages/styled/types/tests.tsx +++ b/packages/styled/types/tests.tsx @@ -221,7 +221,7 @@ const Input5 = styled.input` { // Props forwarding through StyledOptions and FilteringStyledOptions - const fc: React.FC<{ foo: string }> = props =>
+ const fc: React.FC<{ foo: string }> = () => null styled(fc, { shouldForwardProp: (prop: 'foo') => true })({}) @@ -230,52 +230,61 @@ const Input5 = styled.input` // $ExpectError styled(fc, { shouldForwardProp: (prop: 'bar') => true })({}) - const shouldForwardProp1 = (prop: 'foo') => true - styled(fc, { shouldForwardProp: shouldForwardProp1 })({}) + styled(fc, { shouldForwardProp: (prop: 'foo') => true })({}) - const shouldForwardProp2: StyledOptions['shouldForwardProp'] = ( + // $ExpectError + const shouldForwardProp1: StyledOptions['shouldForwardProp'] = ( prop: 'unknown' ) => true - styled(fc, { shouldForwardProp: shouldForwardProp2 })({}) + styled(fc, { shouldForwardProp: shouldForwardProp1 })({}) - const shouldForwardProp3 = (prop: 'unknown') => true // $ExpectError - styled(fc, { shouldForwardProp: shouldForwardProp3 })({}) + styled(fc, { shouldForwardProp: (prop: 'unknown') => true })({}) // $ExpectError - const shouldForwardProp4: StyledOptions<{ + const shouldForwardProp2: StyledOptions<{ foo: string }>['shouldForwardProp'] = (prop: 'unknown') => true - const shouldForwardProp5 = (prop: 'foo'): prop is 'foo' => true - styled(fc, { shouldForwardProp: shouldForwardProp5 })({}) + styled(fc, { shouldForwardProp: (prop: 'foo'): prop is 'foo' => true })({}) + + const shouldForwardProp3: FilteringStyledOptions['shouldForwardProp'] = ( + prop: string + ): prop is 'foo' => true - const shouldForwardProp6: FilteringStyledOptions['shouldForwardProp'] = ( + // $ExpectError + const shouldForwardProp4: FilteringStyledOptions['shouldForwardProp'] = ( prop: 'foo' ): prop is 'foo' => true - const shouldForwardProp7: FilteringStyledOptions<{ + const shouldForwardProp5: FilteringStyledOptions<{ foo: string }>['shouldForwardProp'] = (prop: 'foo'): prop is 'foo' => true // $ExpectError - const shouldForwardProp8: FilteringStyledOptions<{ + const shouldForwardProp6: FilteringStyledOptions<{ foo: string }>['shouldForwardProp'] = (prop: 'unknown'): prop is 'unknown' => true - const shouldForwardProp9: FilteringStyledOptions< + const shouldForwardProp7: FilteringStyledOptions< { foo: string; bar: string }, 'foo' >['shouldForwardProp'] = (prop: 'foo' | 'bar'): prop is 'foo' => true // $ExpectError - const shouldForwardProp10: FilteringStyledOptions< + const shouldForwardProp8: FilteringStyledOptions< { foo: string; bar: string }, 'foo' >['shouldForwardProp'] = (prop: 'foo' | 'bar'): prop is 'bar' => true + styled('div', { + shouldForwardProp: (prop: keyof JSX.IntrinsicElements['div']) => true + })({}) + + // $ExpectError styled('div', { shouldForwardProp: (prop: 'color') => true })({}) + // $ExpectError styled('div', { shouldForwardProp: (prop: 'color'): prop is 'color' => true })({}) From ac3f8c7a975ea6166194226ed3a412becf7c6794 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Mon, 30 May 2022 18:09:23 +0200 Subject: [PATCH 22/25] Tweak `FilteringStyledOptions` and `StyledOptions` interfaces --- packages/native/types/base.d.ts | 8 ++++---- packages/styled/types/base.d.ts | 10 ++++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/packages/native/types/base.d.ts b/packages/native/types/base.d.ts index 6b6e11e4a..65c353625 100644 --- a/packages/native/types/base.d.ts +++ b/packages/native/types/base.d.ts @@ -63,14 +63,14 @@ export type Interpolation< * Practical sense: you can define and reuse atomic `shouldForwardProp` filters that are strictly bound with some `ForwardedProps` type. */ export interface FilteringStyledOptions< - Props = Record, + Props extends {} = {}, ForwardedProps extends keyof Props = keyof Props > { - shouldForwardProp?: (propName: keyof Props) => propName is ForwardedProps + shouldForwardProp?: (propName: PropertyKey) => propName is ForwardedProps } -export interface StyledOptions> { - shouldForwardProp?: (propName: keyof Props) => boolean +export interface StyledOptions { + shouldForwardProp?: (propName: PropertyKey) => boolean } /** diff --git a/packages/styled/types/base.d.ts b/packages/styled/types/base.d.ts index b1905352c..ea2d6d758 100644 --- a/packages/styled/types/base.d.ts +++ b/packages/styled/types/base.d.ts @@ -18,17 +18,19 @@ export { ComponentSelector, Interpolation } * Practical sense: you can define and reuse atomic `shouldForwardProp` filters that are strictly bound with some `ForwardedProps` type. */ export interface FilteringStyledOptions< - Props = Record, + Props extends {} = {}, ForwardedProps extends keyof Props = keyof Props > { label?: string - shouldForwardProp?: (propName: keyof Props) => propName is ForwardedProps + // we can't use `keyof Props` here because we need to include `AdditionalProps` and those aren't available yet + // `Props` represent the actual props of a component while `AdditionalProps` represent props used only for styling purposes + shouldForwardProp?: (propName: PropertyKey) => propName is ForwardedProps target?: string } -export interface StyledOptions> { +export interface StyledOptions { label?: string - shouldForwardProp?: (propName: keyof Props) => boolean + shouldForwardProp?: (propName: PropertyKey) => boolean target?: string } From fce092c2dd8e36f0842f129817f9c26629039b05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Mon, 30 May 2022 19:41:11 +0200 Subject: [PATCH 23/25] Change `Props` constraint --- packages/native/types/base.d.ts | 4 ++-- packages/styled/types/base.d.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/native/types/base.d.ts b/packages/native/types/base.d.ts index 65c353625..5cd28783c 100644 --- a/packages/native/types/base.d.ts +++ b/packages/native/types/base.d.ts @@ -63,13 +63,13 @@ export type Interpolation< * Practical sense: you can define and reuse atomic `shouldForwardProp` filters that are strictly bound with some `ForwardedProps` type. */ export interface FilteringStyledOptions< - Props extends {} = {}, + Props = {}, ForwardedProps extends keyof Props = keyof Props > { shouldForwardProp?: (propName: PropertyKey) => propName is ForwardedProps } -export interface StyledOptions { +export interface StyledOptions { shouldForwardProp?: (propName: PropertyKey) => boolean } diff --git a/packages/styled/types/base.d.ts b/packages/styled/types/base.d.ts index ea2d6d758..3363a1270 100644 --- a/packages/styled/types/base.d.ts +++ b/packages/styled/types/base.d.ts @@ -18,7 +18,7 @@ export { ComponentSelector, Interpolation } * Practical sense: you can define and reuse atomic `shouldForwardProp` filters that are strictly bound with some `ForwardedProps` type. */ export interface FilteringStyledOptions< - Props extends {} = {}, + Props = {}, ForwardedProps extends keyof Props = keyof Props > { label?: string @@ -28,7 +28,7 @@ export interface FilteringStyledOptions< target?: string } -export interface StyledOptions { +export interface StyledOptions { label?: string shouldForwardProp?: (propName: PropertyKey) => boolean target?: string From 59e8aece3f139d02684c861582a8141a172d1050 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Mon, 30 May 2022 21:52:10 +0200 Subject: [PATCH 24/25] Tweak type-level tests around `shouldForwardProp` --- packages/native/types/base.d.ts | 8 ++++---- packages/native/types/tests.tsx | 6 ++++++ packages/styled/types/base.d.ts | 10 ++++------ packages/styled/types/tests.tsx | 23 ++++++++++++++++------- 4 files changed, 30 insertions(+), 17 deletions(-) diff --git a/packages/native/types/base.d.ts b/packages/native/types/base.d.ts index 5cd28783c..f0fee1095 100644 --- a/packages/native/types/base.d.ts +++ b/packages/native/types/base.d.ts @@ -63,14 +63,14 @@ export type Interpolation< * Practical sense: you can define and reuse atomic `shouldForwardProp` filters that are strictly bound with some `ForwardedProps` type. */ export interface FilteringStyledOptions< - Props = {}, + Props = Record, ForwardedProps extends keyof Props = keyof Props > { - shouldForwardProp?: (propName: PropertyKey) => propName is ForwardedProps + shouldForwardProp?: (propName: string) => propName is ForwardedProps & string } -export interface StyledOptions { - shouldForwardProp?: (propName: PropertyKey) => boolean +export interface StyledOptions> { + shouldForwardProp?: (propName: string) => boolean } /** diff --git a/packages/native/types/tests.tsx b/packages/native/types/tests.tsx index cb87f09c5..002865633 100644 --- a/packages/native/types/tests.tsx +++ b/packages/native/types/tests.tsx @@ -175,9 +175,15 @@ export const ImageFullWidthContained = styled.Image` { // Props forwarding through StyledOptions and FilteringStyledOptions + styled(View, { shouldForwardProp: (prop: string) => true })({}) + // $ExpectError styled(View, { shouldForwardProp: (prop: 'testID') => true })({}) styled(View, { + shouldForwardProp: (prop: string): prop is 'testID' => true + })({}) + styled(View, { + // $ExpectError shouldForwardProp: (prop: 'testID'): prop is 'testID' => true })({}) diff --git a/packages/styled/types/base.d.ts b/packages/styled/types/base.d.ts index 3363a1270..5680fb56f 100644 --- a/packages/styled/types/base.d.ts +++ b/packages/styled/types/base.d.ts @@ -18,19 +18,17 @@ export { ComponentSelector, Interpolation } * Practical sense: you can define and reuse atomic `shouldForwardProp` filters that are strictly bound with some `ForwardedProps` type. */ export interface FilteringStyledOptions< - Props = {}, + Props = Record, ForwardedProps extends keyof Props = keyof Props > { label?: string - // we can't use `keyof Props` here because we need to include `AdditionalProps` and those aren't available yet - // `Props` represent the actual props of a component while `AdditionalProps` represent props used only for styling purposes - shouldForwardProp?: (propName: PropertyKey) => propName is ForwardedProps + shouldForwardProp?: (propName: string) => propName is ForwardedProps & string target?: string } -export interface StyledOptions { +export interface StyledOptions> { label?: string - shouldForwardProp?: (propName: PropertyKey) => boolean + shouldForwardProp?: (propName: string) => boolean target?: string } diff --git a/packages/styled/types/tests.tsx b/packages/styled/types/tests.tsx index 266843120..97c17a073 100644 --- a/packages/styled/types/tests.tsx +++ b/packages/styled/types/tests.tsx @@ -223,13 +223,16 @@ const Input5 = styled.input` const fc: React.FC<{ foo: string }> = () => null + // we can't accept a "known" prop here because we need to include `AdditionalProps` and those aren't available yet + // `Props` represent the actual props of a component while `AdditionalProps` represent props used only for styling purposes + // $ExpectError styled(fc, { shouldForwardProp: (prop: 'foo') => true })({}) styled(fc, { shouldForwardProp: (prop: string) => true })({}) // $ExpectError styled(fc, { shouldForwardProp: (prop: 'bar') => true })({}) - + // $ExpectError styled(fc, { shouldForwardProp: (prop: 'foo') => true })({}) // $ExpectError @@ -246,6 +249,8 @@ const Input5 = styled.input` foo: string }>['shouldForwardProp'] = (prop: 'unknown') => true + styled(fc, { shouldForwardProp: (prop: string): prop is 'foo' => true })({}) + // $ExpectError styled(fc, { shouldForwardProp: (prop: 'foo'): prop is 'foo' => true })({}) const shouldForwardProp3: FilteringStyledOptions['shouldForwardProp'] = ( @@ -259,33 +264,37 @@ const Input5 = styled.input` const shouldForwardProp5: FilteringStyledOptions<{ foo: string + }>['shouldForwardProp'] = (prop: string): prop is 'foo' => true + // $ExpectError + const shouldForwardProp6: FilteringStyledOptions<{ + foo: string }>['shouldForwardProp'] = (prop: 'foo'): prop is 'foo' => true // $ExpectError - const shouldForwardProp6: FilteringStyledOptions<{ + const shouldForwardProp7: FilteringStyledOptions<{ foo: string }>['shouldForwardProp'] = (prop: 'unknown'): prop is 'unknown' => true - const shouldForwardProp7: FilteringStyledOptions< + const shouldForwardProp8: FilteringStyledOptions< { foo: string; bar: string }, 'foo' - >['shouldForwardProp'] = (prop: 'foo' | 'bar'): prop is 'foo' => true + >['shouldForwardProp'] = (prop: string): prop is 'foo' => true // $ExpectError - const shouldForwardProp8: FilteringStyledOptions< + const shouldForwardProp9: FilteringStyledOptions< { foo: string; bar: string }, 'foo' >['shouldForwardProp'] = (prop: 'foo' | 'bar'): prop is 'bar' => true styled('div', { - shouldForwardProp: (prop: keyof JSX.IntrinsicElements['div']) => true + shouldForwardProp: (prop: string) => true })({}) // $ExpectError styled('div', { shouldForwardProp: (prop: 'color') => true })({}) - // $ExpectError styled('div', { + // $ExpectError shouldForwardProp: (prop: 'color'): prop is 'color' => true })({}) From 682313b8151db4ab4517337a5a73556afa22ed55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Sun, 12 Jun 2022 10:16:57 +0200 Subject: [PATCH 25/25] add changesets --- .changeset/tall-flies-smoke.md | 8 ++++++++ .changeset/thirty-boats-hang.md | 6 ++++++ packages/native/types/base.d.ts | 5 +---- packages/styled/types/base.d.ts | 5 +---- 4 files changed, 16 insertions(+), 8 deletions(-) create mode 100644 .changeset/tall-flies-smoke.md create mode 100644 .changeset/thirty-boats-hang.md diff --git a/.changeset/tall-flies-smoke.md b/.changeset/tall-flies-smoke.md new file mode 100644 index 000000000..cdb24cc23 --- /dev/null +++ b/.changeset/tall-flies-smoke.md @@ -0,0 +1,8 @@ +--- +'@emotion/native': patch +'@emotion/styled': patch +--- + +author: @Andarist + +`shouldForwardProp` has been changed from being a bivariant method to a contravariant function - it improves the type-safety for those that type this option. diff --git a/.changeset/thirty-boats-hang.md b/.changeset/thirty-boats-hang.md new file mode 100644 index 000000000..8b34829c5 --- /dev/null +++ b/.changeset/thirty-boats-hang.md @@ -0,0 +1,6 @@ +--- +'@emotion/native': patch +'@emotion/styled': patch +--- + +`FilteringStyledOptions` and `StyledOptions` types no longer require a type argument for the `Props` generic. diff --git a/packages/native/types/base.d.ts b/packages/native/types/base.d.ts index bd7d4d479..a14f22bad 100644 --- a/packages/native/types/base.d.ts +++ b/packages/native/types/base.d.ts @@ -58,10 +58,7 @@ export type Interpolation< | ArrayInterpolation | FunctionInterpolation -/** - * Same as StyledOptions but shouldForwardProp must be a type guard (https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates). - * Practical sense: you can define and reuse atomic `shouldForwardProp` filters that are strictly bound with some `ForwardedProps` type. - */ +/** Same as StyledOptions but shouldForwardProp must be a type guard */ export interface FilteringStyledOptions< Props = Record, ForwardedProps extends keyof Props & string = keyof Props & string diff --git a/packages/styled/types/base.d.ts b/packages/styled/types/base.d.ts index 59646dee8..05efbaea4 100644 --- a/packages/styled/types/base.d.ts +++ b/packages/styled/types/base.d.ts @@ -13,10 +13,7 @@ export { export { ComponentSelector, Interpolation } -/** - * Same as StyledOptions but shouldForwardProp must be a type guard (https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates). - * Practical sense: you can define and reuse atomic `shouldForwardProp` filters that are strictly bound with some `ForwardedProps` type. - */ +/** Same as StyledOptions but shouldForwardProp must be a type guard */ export interface FilteringStyledOptions< Props = Record, ForwardedProps extends keyof Props & string = keyof Props & string