Skip to content

Commit 04e94fb

Browse files
committed
wip refining ts types for styles
1 parent 87387ae commit 04e94fb

File tree

8 files changed

+69
-119
lines changed

8 files changed

+69
-119
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@
8888
"mocha": "^3.2.0",
8989
"npmlog": "^4.1.2",
9090
"pre-commit": "^1.1.3",
91-
"prettier": "^1.13.5",
91+
"prettier": "^2.4.0",
9292
"raf": "^3.4.0",
9393
"react": "^16.8.6",
9494
"react-test-renderer": "^16.8.6",

packages/jss/src/index.d.ts

Lines changed: 30 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -6,44 +6,45 @@ import {Properties as CSSProperties, PropertiesHyphen as CSSPropertiesHyphen} fr
66
//
77
// TODO: refactor to only include Observable types if plugin is installed.
88
export interface MinimalObservable<T> {
9-
subscribe(
10-
nextOrObserver: ((value: T) => void) | {next: (value: T) => void}
11-
): {unsubscribe: () => void}
9+
subscribe(nextOrObserver: ((value: T) => void) | {next: (value: T) => void}): {
10+
unsubscribe: () => void
11+
}
1212
}
1313

14-
type Func<P, T, R> = T extends undefined ? ((data: P) => R) : ((data: P & {theme: T}) => R)
14+
type Func<Data, Theme, Style> = Theme extends undefined
15+
? (data: Data) => Style | null | undefined
16+
: (data: Data & {theme: Theme}) => Style | null | undefined
1517

1618
type NormalCssProperties = CSSProperties<string | number> & CSSPropertiesHyphen<string | number>
1719
type NormalCssValues<K> = K extends keyof NormalCssProperties ? NormalCssProperties[K] : JssValue
1820

19-
export type JssStyle<Props = any, Theme = undefined> =
20-
| {
21-
[K in keyof NormalCssProperties]:
22-
| NormalCssValues<K>
23-
| JssStyle<Props, Theme>
24-
| Func<Props, Theme, NormalCssValues<K> | JssStyle<undefined, undefined> | undefined>
25-
| MinimalObservable<NormalCssValues<K> | JssStyle | undefined>
26-
}
27-
| {
28-
[K: string]:
29-
| JssValue
30-
| JssStyle<Props, Theme>
31-
| Func<Props, Theme, JssValue | JssStyle<undefined, undefined> | undefined>
32-
| MinimalObservable<JssValue | JssStyle | undefined>
33-
}
34-
21+
export type JssStyle<Data = any, Theme = undefined> = {
22+
[Key in keyof NormalCssProperties]:
23+
| NormalCssValues<Key>
24+
| JssStyle<Data, Theme>
25+
| Func<Data, Theme, NormalCssValues<Key> | undefined>
26+
| MinimalObservable<NormalCssValues<Key> | JssStyle | undefined>
27+
| null
28+
| undefined
29+
} & // nesting
30+
{
31+
[Key: `${string}&${string}`]: JssStyle<Data, Theme> | null | undefined
32+
}
3533
export type Styles<
3634
Name extends string | number | symbol = string,
37-
Props = unknown,
35+
Data = unknown,
3836
Theme = undefined
39-
> = Record<
40-
Name,
41-
| JssStyle<Props, Theme>
42-
| Array<JssStyle<Props, Theme>>
43-
| string
44-
| Func<Props, Theme, JssStyle<undefined, undefined> | string | null | undefined>
45-
| MinimalObservable<JssStyle | string | null | undefined>
46-
>
37+
> =
38+
| Record<
39+
Name,
40+
| JssStyle<Data, Theme>
41+
| Array<JssStyle<Data, Theme>>
42+
| string
43+
| Func<Data, Theme, JssStyle<undefined, undefined> | string | null | undefined>
44+
| MinimalObservable<JssStyle | string | null | undefined>
45+
>
46+
| Record<`@keyframes ${string}`, Record<'from' | 'to' | `${number}%`, JssStyle<Data, Theme>>>
47+
4748
export type Classes<Name extends string | number | symbol = string> = Record<Name, string>
4849
export type Keyframes<Name extends string = string> = Record<Name, string>
4950

packages/jss/tests/types/Styles.ts

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ const styles: Styles<string, Props> = {
2626
textAlign: 'center',
2727
display: 'flex',
2828
width: '100%',
29-
justifyContent: props => (props.flag ? 'center' : undefined)
29+
justifyContent: (props) => (props.flag ? 'center' : undefined)
3030
},
3131
inner: {
3232
textAlign: 'center',
@@ -37,7 +37,7 @@ const styles: Styles<string, Props> = {
3737
fontSize: 12
3838
}
3939
},
40-
func: props => ({
40+
func: (props) => ({
4141
display: 'flex',
4242
flexDirection: 'column',
4343
justifyContent: 'center',
@@ -47,8 +47,8 @@ const styles: Styles<string, Props> = {
4747
position: 'relative',
4848
pointerEvents: props.flag ? 'none' : null
4949
}),
50-
funcNull: props => null,
51-
funcWithTerm: props => ({
50+
funcNull: (props) => null,
51+
funcWithTerm: (props) => ({
5252
width: props.flag ? 377 : 272,
5353
height: props.flag ? 330 : 400,
5454
boxShadow: '0px 2px 20px rgba(0, 0, 0, 0.08)',
@@ -68,27 +68,19 @@ const styles: Styles<string, Props> = {
6868
},
6969
'@keyframes fadeIn': {
7070
from: {opacity: 0},
71-
to: {opacity: 1}
71+
to: {opacity: 1},
72+
'50%': {opacity: 0.5}
7273
}
7374
}
7475

7576
// Test supplied Props and Theme
7677
// Verify that nested parameter declarations are banned
7778
const stylesPropsAndTheme: Styles<string, Props, Theme> = {
78-
rootParamDeclaration: ({flag, theme}) => ({
79+
// @ts-expect-error Did you mean to call this expression?
80+
rootParamDeclaration: ({flag, theme}: Props & {theme: Theme}) => ({
7981
fontWeight: 'bold',
80-
// @ts-expect-error
81-
nothingAllowed: ({flag, theme}) => ''
82-
}),
83-
anotherClass: {
84-
color: 'red',
85-
innerParamDeclaration1: ({flag, theme}) => '',
86-
innerParamDeclaration2: ({flag, theme}) => ({
87-
backgroundColor: 'blue',
88-
// @ts-expect-error
89-
nothingAllowed: ({flag, theme}) => ''
90-
})
91-
}
82+
color: ({flag, theme}: Props & {theme: Theme}) => 'red'
83+
})
9284
}
9385

9486
// Test the className types

packages/react-jss/src/index.d.ts

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,8 @@ interface WithStylesProps<
4949
/**
5050
* @deprecated Please use `WithStylesProps` instead
5151
*/
52-
type WithStyles<
53-
S extends Styles<any, any, any> | ((theme: any) => Styles<any, any, undefined>)
54-
> = WithStylesProps<S>
52+
type WithStyles<S extends Styles<any, any, any> | ((theme: any) => Styles<any, any, undefined>)> =
53+
WithStylesProps<S>
5554

5655
declare global {
5756
namespace Jss {
@@ -76,10 +75,10 @@ interface CreateUseStylesOptions<Theme = DefaultTheme> extends BaseOptions<Theme
7675
name?: string
7776
}
7877

79-
declare function createUseStyles<C extends string = string, Props = unknown, Theme = DefaultTheme>(
80-
styles: Styles<C, Props, Theme> | ((theme: Theme) => Styles<C, Props, undefined>),
78+
declare function createUseStyles<C extends string = string, Data = unknown, Theme = DefaultTheme>(
79+
styles: Styles<C, Data, Theme> | ((theme: Theme) => Styles<C, Data, Theme>),
8180
options?: CreateUseStylesOptions<Theme>
82-
): (data?: Props & {theme?: Theme}) => Classes<C>
81+
): (data?: Data & {theme?: Theme}) => Classes<C>
8382

8483
type GetProps<C> = C extends ComponentType<infer P> ? P : never
8584

@@ -88,9 +87,7 @@ declare function withStyles<ClassNames extends string | number | symbol, Props,
8887
| Styles<ClassNames, Props, Theme>
8988
| ((theme: Theme) => Styles<ClassNames, Props, undefined>),
9089
options?: WithStylesOptions
91-
): <C>(
92-
comp: C
93-
) => ComponentType<
90+
): <C>(comp: C) => ComponentType<
9491
JSX.LibraryManagedAttributes<
9592
C,
9693
Omit<GetProps<C>, 'classes'> & {

packages/react-jss/tests/types/createUseStyles.ts

Lines changed: 13 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const expectedCustomTheme: MyTheme = {color: 'red'}
1616

1717
/* -------------------- THEME ARGUMENT -------------------- */
1818
// Regular, static styles work fine
19-
const themeArg1 = createUseStyles(theme => ({
19+
const themeArg1 = createUseStyles((theme) => ({
2020
someClassName: '',
2121
anotherClassName: {
2222
fontWeight: 'bold'
@@ -26,20 +26,20 @@ const themeArg1ClassesPass = themeArg1()
2626

2727
// Theme type assumed to be the default
2828
// Nested theme declaration banned
29-
// @ts-expect-error
30-
const themeArg2 = createUseStyles(theme => ({
31-
themeNotAllowed: ({theme: innerTheme}) => ({
32-
fontWeight: 'bold'
29+
const themeArg2 = createUseStyles((parentTheme) => ({
30+
themeNotAllowed: ({theme}: {theme: MyTheme}) => ({
31+
color: theme.color
3332
})
3433
}))
3534
// @ts-expect-error
3635
const themeArg2ClassesFail = themeArg2({theme: {}})
3736
// @ts-expect-error
3837
const themeArg2ClassesFail2 = themeArg2({theme: expectedCustomTheme})
39-
const themeArg2ClassesPass = themeArg2({theme: expectedDefaultTheme})
38+
// @ts-expect-error
39+
const themeArg2ClassesFail2 = themeArg2({theme: expectedDefaultTheme})
4040

4141
// Props declaration is allowed
42-
const themeArg3 = createUseStyles<string, MyProps>(theme => ({
42+
const themeArg3 = createUseStyles<string, MyProps>((theme) => ({
4343
onlyPropsAllowed: ({...props}) => ({
4444
fontWeight: 'bold'
4545
})
@@ -52,16 +52,15 @@ const themeArg3ClassesPass = themeArg3(expectedCustomProps)
5252
const themeArg3ClassesPass2 = themeArg3({...expectedCustomProps, theme: expectedDefaultTheme})
5353

5454
// Nested props declaration banned
55-
const themeArg4 = createUseStyles<string, MyProps>(theme => ({
55+
const themeArg4 = createUseStyles<string, MyProps>((theme) => ({
5656
onlyPropsAllowed: ({...props}) => ({
5757
fontWeight: 'bold',
58-
// @ts-expect-error
5958
propsNotAllowed: ({...innerProps}) => ''
6059
})
6160
}))
6261

6362
// Supplied theme type is acknowledged
64-
const themeArg5 = createUseStyles<string, unknown, MyTheme>(theme => ({}))
63+
const themeArg5 = createUseStyles<string, unknown, MyTheme>((theme) => ({}))
6564
// @ts-expect-error
6665
const themeArg5ClassesFail = themeArg5({theme: {}})
6766
// @ts-expect-error
@@ -81,7 +80,7 @@ const themeArg6ClassesFail2 = themeArg6({theme: expectedDefaultTheme})
8180
const themeArg6ClassesPass = themeArg6({theme: expectedCustomTheme})
8281

8382
// Props can be determined implicitly
84-
const themeArg7 = createUseStyles(theme => ({
83+
const themeArg7 = createUseStyles((theme) => ({
8584
checkbox: ({property}: MyProps) => ({
8685
borderColor: property
8786
})
@@ -172,53 +171,14 @@ const noThemeArg4ClassesPass2 = noThemeArg4({...expectedCustomProps, theme: expe
172171
const noThemeArg5 = createUseStyles<string, MyProps, MyTheme>({
173172
singleNest: {
174173
fontWeight: 'bold',
175-
singleValue: ({property, theme}) => '',
176-
nestOne: ({property, theme}) => ({
174+
// @ts-expect-error
175+
nestOne: ({property, theme}: MyProps & {theme: MyTheme}) => ({
177176
color: 'red',
178-
// @ts-expect-error
179-
nothingAllowed: ({theme: innerTheme, ...innerProps}) => ''
177+
display: () => 'block'
180178
})
181179
}
182180
})
183181

184-
// Nested declarations are banned (double nest test)
185-
const noThemeArg6 = createUseStyles<string, MyProps, MyTheme>({
186-
doubleNest: {
187-
fontWeight: 'bold',
188-
singleValue: ({property, theme}) => '',
189-
firstNest: {
190-
color: 'red',
191-
innerSingleValue: ({property, theme}) => '',
192-
secondNest: ({property, theme}) => ({
193-
backgroundColor: 'blue',
194-
// @ts-expect-error
195-
nothingAllowed: ({theme: innerTheme, ...innerProps}) => ''
196-
})
197-
}
198-
}
199-
})
200-
201-
// Nested declarations are banned (triple nest test)
202-
const noThemeArg7 = createUseStyles<string, MyProps, MyTheme>({
203-
tripleNest: {
204-
fontWeight: 'bold',
205-
singleValue: ({property, theme}) => '',
206-
firstNest: {
207-
color: 'red',
208-
innerSingleValue: ({property, theme}) => '',
209-
secondNest: {
210-
backgroundColor: 'blue',
211-
innerMostSingleValue: ({property, theme}) => '',
212-
thirdNest: ({property, theme}) => ({
213-
display: 'block',
214-
// @ts-expect-error
215-
nothingAllowed: ({theme: innerMostTheme, ...innerMostProps}) => ''
216-
})
217-
}
218-
}
219-
}
220-
})
221-
222182
// Props can be determined implicitly
223183
const noThemeArg8 = createUseStyles({
224184
checkbox: ({property}: MyProps) => ({

packages/react-jss/tests/types/docs.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@ type RuleNames = 'myButton' | 'myLabel'
88
interface ButtonProps {
99
children?: React.ReactNode
1010
spacing?: number
11-
fontWeight?: string
12-
labelColor?: string
11+
fontWeight?: 'bold'
12+
labelColor?: 'red'
1313
}
1414

1515
interface CustomTheme {
16-
background: string
16+
background: 'gray'
1717
}
1818

1919
const useStyles = createUseStyles<RuleNames, ButtonProps, CustomTheme>({

packages/react-jss/tests/types/withStyles.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ function functionPlainObject(theme: MyTheme) {
3131
anotherClassName: {
3232
fontWeight: 'bold'
3333
}
34-
}
34+
} as const
3535
}
3636
ResultingComponent = withStyles(functionPlainObject)(SimpleComponent)
3737
ComponentTest = () => <ResultingComponent property="" />
@@ -80,7 +80,7 @@ const plainObject = {
8080
anotherClassName: {
8181
fontWeight: 'bold'
8282
}
83-
}
83+
} as const
8484
ResultingComponent = withStyles(plainObject)(SimpleComponent)
8585
ComponentTest = () => <ResultingComponent property="" />
8686

yarn.lock

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8140,10 +8140,10 @@ preserve@^0.2.0:
81408140
resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b"
81418141
integrity sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=
81428142

8143-
prettier@^1.13.5:
8144-
version "1.14.2"
8145-
resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.14.2.tgz#0ac1c6e1a90baa22a62925f41963c841983282f9"
8146-
integrity sha512-McHPg0n1pIke+A/4VcaS2en+pTNjy4xF+Uuq86u/5dyDO59/TtFZtQ708QIRkEZ3qwKz3GVkVa6mpxK/CpB8Rg==
8143+
prettier@^2.4.0:
8144+
version "2.4.0"
8145+
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.4.0.tgz#85bdfe0f70c3e777cf13a4ffff39713ca6f64cba"
8146+
integrity sha512-DsEPLY1dE5HF3BxCRBmD4uYZ+5DCbvatnolqTqcxEgKVZnL2kUfyu7b8pPQ5+hTBkdhU9SLUmK0/pHb07RE4WQ==
81478147

81488148
pretty-format@^26.6.2:
81498149
version "26.6.2"

0 commit comments

Comments
 (0)