From a570f35acadbb1446e542dfe95357bf60e4b490c Mon Sep 17 00:00:00 2001 From: Oleg Isonen Date: Mon, 6 Sep 2021 22:16:35 +0200 Subject: [PATCH 1/5] upgrade typescript to 4.4.2 --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 54dd049f4..508be5aff 100644 --- a/package.json +++ b/package.json @@ -98,7 +98,7 @@ "rollup-plugin-terser": "^7.0.2", "shelljs": "^0.8.2", "sinon": "4.5.0", - "typescript": "^3.7.0", + "typescript": "^4.4.2", "webpack": "^4.28.3", "zen-observable": "^0.6.0" } diff --git a/yarn.lock b/yarn.lock index eed488c5d..2e35607bf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10000,10 +10000,10 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -typescript@^3.7.0: - version "3.9.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.3.tgz#d3ac8883a97c26139e42df5e93eeece33d610b8a" - integrity sha512-D/wqnB2xzNFIcoBG9FG8cXRDjiqSTbG2wd8DMZeQyJlP1vfTkIxH4GKveWaEBYySKIg+USu+E+EDIR47SqnaMQ== +typescript@^4.4.2: + version "4.4.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.4.2.tgz#6d618640d430e3569a1dfb44f7d7e600ced3ee86" + integrity sha512-gzP+t5W4hdy4c+68bfcv0t400HVJMMd2+H9B7gae1nQlBzCqvrXX+6GL/b3GAgyTH966pzrZ70/fRjwAtZksSQ== uglify-js@^3.1.4: version "3.8.0" From f55414e59f7e85fef4e255c40c649c8ccb5dda57 Mon Sep 17 00:00:00 2001 From: Oleg Isonen Date: Mon, 6 Sep 2021 22:22:41 +0200 Subject: [PATCH 2/5] temporary hotfix the errors from typescript 4 migration --- packages/react-jss/tests/types/withStyles.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/react-jss/tests/types/withStyles.tsx b/packages/react-jss/tests/types/withStyles.tsx index b7dfa9aa1..c77f7ad32 100644 --- a/packages/react-jss/tests/types/withStyles.tsx +++ b/packages/react-jss/tests/types/withStyles.tsx @@ -163,8 +163,9 @@ function passingFunctionNullTheme(theme: MyTheme): Styles } } } - -// @ts-expect-error +// TODO clarify all these tests, because they started to work/fail differently +// after migration to typescript 4 and probably rely on a fragile a ts api withStyles(failingFunctionRedefineTheme)(SimpleComponent) withStyles(passingFunctionUnknownTheme)(SimpleComponent) +// @ts-expect-error withStyles(passingFunctionNullTheme)(SimpleComponent) From 81ec5b98c4ff8fd638447aec67671e2aba20dc34 Mon Sep 17 00:00:00 2001 From: Oleg Isonen Date: Mon, 6 Sep 2021 22:25:21 +0200 Subject: [PATCH 3/5] properly support hyphen separated properties --- packages/jss/src/index.d.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/jss/src/index.d.ts b/packages/jss/src/index.d.ts index b26b2be57..20184e9e5 100644 --- a/packages/jss/src/index.d.ts +++ b/packages/jss/src/index.d.ts @@ -1,4 +1,4 @@ -import {Properties as CSSProperties} from 'csstype' +import {Properties as CSSProperties, PropertiesHyphen as CSSPropertiesHyphen} from 'csstype' // Observable support is included as a plugin. Including it here allows // TypeScript users to use Observables, which could be confusing if a user @@ -13,7 +13,7 @@ export interface MinimalObservable { type Func = T extends undefined ? ((data: P) => R) : ((data: P & {theme: T}) => R) -type NormalCssProperties = CSSProperties +type NormalCssProperties = CSSProperties & CSSPropertiesHyphen type NormalCssValues = K extends keyof NormalCssProperties ? NormalCssProperties[K] : JssValue export type JssStyle = From d2a2b4b1129976e43685a1e7c071d188e62805b7 Mon Sep 17 00:00:00 2001 From: Oleg Isonen Date: Sun, 12 Sep 2021 13:09:06 +0200 Subject: [PATCH 4/5] remove an inexisting failing case when theme is any --- packages/react-jss/tests/types/withStyles.tsx | 22 +++++-------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/packages/react-jss/tests/types/withStyles.tsx b/packages/react-jss/tests/types/withStyles.tsx index b7dfa9aa1..0527b2341 100644 --- a/packages/react-jss/tests/types/withStyles.tsx +++ b/packages/react-jss/tests/types/withStyles.tsx @@ -136,8 +136,7 @@ ComponentTest = () => /* -------------------- Failing Cases -------------------- */ -// A function argument cannot provide another defined theme type conflicting with `undefined` -function failingFunctionRedefineTheme(theme: MyTheme): Styles { +function failingFunctionWrongTheme(theme: MyTheme): Styles { return { someClassName: '', anotherClassName: { @@ -146,7 +145,7 @@ function failingFunctionRedefineTheme(theme: MyTheme): Styles { +function failingFunctionNullTheme(theme: MyTheme): Styles { return { someClassName: '', anotherClassName: { @@ -155,16 +154,7 @@ function passingFunctionUnknownTheme(theme: MyTheme): Styles { - return { - someClassName: '', - anotherClassName: { - fontWeight: 'bold' - } - } -} - -// @ts-expect-error -withStyles(failingFunctionRedefineTheme)(SimpleComponent) -withStyles(passingFunctionUnknownTheme)(SimpleComponent) -withStyles(passingFunctionNullTheme)(SimpleComponent) +// @ts-expect-error - can't use a wrong theme +withStyles(failingFunctionWrongTheme)(SimpleComponent) +// @ts-expect-error - can't use null as a theme +withStyles(failingFunctionNullTheme)(SimpleComponent) From 04e94fb0eace518e4c66e618d495acfa342e4a88 Mon Sep 17 00:00:00 2001 From: Oleg Isonen Date: Mon, 13 Sep 2021 16:34:14 +0200 Subject: [PATCH 5/5] wip refining ts types for styles --- package.json | 2 +- packages/jss/src/index.d.ts | 59 +++++++++-------- packages/jss/tests/types/Styles.ts | 28 +++----- packages/react-jss/src/index.d.ts | 15 ++--- .../react-jss/tests/types/createUseStyles.ts | 66 ++++--------------- packages/react-jss/tests/types/docs.tsx | 6 +- packages/react-jss/tests/types/withStyles.tsx | 4 +- yarn.lock | 8 +-- 8 files changed, 69 insertions(+), 119 deletions(-) diff --git a/package.json b/package.json index 508be5aff..f3229d977 100644 --- a/package.json +++ b/package.json @@ -88,7 +88,7 @@ "mocha": "^3.2.0", "npmlog": "^4.1.2", "pre-commit": "^1.1.3", - "prettier": "^1.13.5", + "prettier": "^2.4.0", "raf": "^3.4.0", "react": "^16.8.6", "react-test-renderer": "^16.8.6", diff --git a/packages/jss/src/index.d.ts b/packages/jss/src/index.d.ts index 20184e9e5..582123810 100644 --- a/packages/jss/src/index.d.ts +++ b/packages/jss/src/index.d.ts @@ -6,44 +6,45 @@ import {Properties as CSSProperties, PropertiesHyphen as CSSPropertiesHyphen} fr // // TODO: refactor to only include Observable types if plugin is installed. export interface MinimalObservable { - subscribe( - nextOrObserver: ((value: T) => void) | {next: (value: T) => void} - ): {unsubscribe: () => void} + subscribe(nextOrObserver: ((value: T) => void) | {next: (value: T) => void}): { + unsubscribe: () => void + } } -type Func = T extends undefined ? ((data: P) => R) : ((data: P & {theme: T}) => R) +type Func = Theme extends undefined + ? (data: Data) => Style | null | undefined + : (data: Data & {theme: Theme}) => Style | null | undefined type NormalCssProperties = CSSProperties & CSSPropertiesHyphen type NormalCssValues = K extends keyof NormalCssProperties ? NormalCssProperties[K] : JssValue -export type JssStyle = - | { - [K in keyof NormalCssProperties]: - | NormalCssValues - | JssStyle - | Func | JssStyle | undefined> - | MinimalObservable | JssStyle | undefined> - } - | { - [K: string]: - | JssValue - | JssStyle - | Func | undefined> - | MinimalObservable - } - +export type JssStyle = { + [Key in keyof NormalCssProperties]: + | NormalCssValues + | JssStyle + | Func | undefined> + | MinimalObservable | JssStyle | undefined> + | null + | undefined +} & // nesting +{ + [Key: `${string}&${string}`]: JssStyle | null | undefined +} export type Styles< Name extends string | number | symbol = string, - Props = unknown, + Data = unknown, Theme = undefined -> = Record< - Name, - | JssStyle - | Array> - | string - | Func | string | null | undefined> - | MinimalObservable -> +> = + | Record< + Name, + | JssStyle + | Array> + | string + | Func | string | null | undefined> + | MinimalObservable + > + | Record<`@keyframes ${string}`, Record<'from' | 'to' | `${number}%`, JssStyle>> + export type Classes = Record export type Keyframes = Record diff --git a/packages/jss/tests/types/Styles.ts b/packages/jss/tests/types/Styles.ts index 45f06f4bb..dd2fd501b 100644 --- a/packages/jss/tests/types/Styles.ts +++ b/packages/jss/tests/types/Styles.ts @@ -26,7 +26,7 @@ const styles: Styles = { textAlign: 'center', display: 'flex', width: '100%', - justifyContent: props => (props.flag ? 'center' : undefined) + justifyContent: (props) => (props.flag ? 'center' : undefined) }, inner: { textAlign: 'center', @@ -37,7 +37,7 @@ const styles: Styles = { fontSize: 12 } }, - func: props => ({ + func: (props) => ({ display: 'flex', flexDirection: 'column', justifyContent: 'center', @@ -47,8 +47,8 @@ const styles: Styles = { position: 'relative', pointerEvents: props.flag ? 'none' : null }), - funcNull: props => null, - funcWithTerm: props => ({ + funcNull: (props) => null, + funcWithTerm: (props) => ({ width: props.flag ? 377 : 272, height: props.flag ? 330 : 400, boxShadow: '0px 2px 20px rgba(0, 0, 0, 0.08)', @@ -68,27 +68,19 @@ const styles: Styles = { }, '@keyframes fadeIn': { from: {opacity: 0}, - to: {opacity: 1} + to: {opacity: 1}, + '50%': {opacity: 0.5} } } // Test supplied Props and Theme // Verify that nested parameter declarations are banned const stylesPropsAndTheme: Styles = { - rootParamDeclaration: ({flag, theme}) => ({ + // @ts-expect-error Did you mean to call this expression? + rootParamDeclaration: ({flag, theme}: Props & {theme: Theme}) => ({ fontWeight: 'bold', - // @ts-expect-error - nothingAllowed: ({flag, theme}) => '' - }), - anotherClass: { - color: 'red', - innerParamDeclaration1: ({flag, theme}) => '', - innerParamDeclaration2: ({flag, theme}) => ({ - backgroundColor: 'blue', - // @ts-expect-error - nothingAllowed: ({flag, theme}) => '' - }) - } + color: ({flag, theme}: Props & {theme: Theme}) => 'red' + }) } // Test the className types diff --git a/packages/react-jss/src/index.d.ts b/packages/react-jss/src/index.d.ts index 00842fc88..aeeccef1e 100644 --- a/packages/react-jss/src/index.d.ts +++ b/packages/react-jss/src/index.d.ts @@ -49,9 +49,8 @@ interface WithStylesProps< /** * @deprecated Please use `WithStylesProps` instead */ -type WithStyles< - S extends Styles | ((theme: any) => Styles) -> = WithStylesProps +type WithStyles | ((theme: any) => Styles)> = + WithStylesProps declare global { namespace Jss { @@ -76,10 +75,10 @@ interface CreateUseStylesOptions extends BaseOptions( - styles: Styles | ((theme: Theme) => Styles), +declare function createUseStyles( + styles: Styles | ((theme: Theme) => Styles), options?: CreateUseStylesOptions -): (data?: Props & {theme?: Theme}) => Classes +): (data?: Data & {theme?: Theme}) => Classes type GetProps = C extends ComponentType ? P : never @@ -88,9 +87,7 @@ declare function withStyles | ((theme: Theme) => Styles), options?: WithStylesOptions -): ( - comp: C -) => ComponentType< +): (comp: C) => ComponentType< JSX.LibraryManagedAttributes< C, Omit, 'classes'> & { diff --git a/packages/react-jss/tests/types/createUseStyles.ts b/packages/react-jss/tests/types/createUseStyles.ts index 7795c4f42..cc2a8bfe3 100644 --- a/packages/react-jss/tests/types/createUseStyles.ts +++ b/packages/react-jss/tests/types/createUseStyles.ts @@ -16,7 +16,7 @@ const expectedCustomTheme: MyTheme = {color: 'red'} /* -------------------- THEME ARGUMENT -------------------- */ // Regular, static styles work fine -const themeArg1 = createUseStyles(theme => ({ +const themeArg1 = createUseStyles((theme) => ({ someClassName: '', anotherClassName: { fontWeight: 'bold' @@ -26,20 +26,20 @@ const themeArg1ClassesPass = themeArg1() // Theme type assumed to be the default // Nested theme declaration banned -// @ts-expect-error -const themeArg2 = createUseStyles(theme => ({ - themeNotAllowed: ({theme: innerTheme}) => ({ - fontWeight: 'bold' +const themeArg2 = createUseStyles((parentTheme) => ({ + themeNotAllowed: ({theme}: {theme: MyTheme}) => ({ + color: theme.color }) })) // @ts-expect-error const themeArg2ClassesFail = themeArg2({theme: {}}) // @ts-expect-error const themeArg2ClassesFail2 = themeArg2({theme: expectedCustomTheme}) -const themeArg2ClassesPass = themeArg2({theme: expectedDefaultTheme}) +// @ts-expect-error +const themeArg2ClassesFail2 = themeArg2({theme: expectedDefaultTheme}) // Props declaration is allowed -const themeArg3 = createUseStyles(theme => ({ +const themeArg3 = createUseStyles((theme) => ({ onlyPropsAllowed: ({...props}) => ({ fontWeight: 'bold' }) @@ -52,16 +52,15 @@ const themeArg3ClassesPass = themeArg3(expectedCustomProps) const themeArg3ClassesPass2 = themeArg3({...expectedCustomProps, theme: expectedDefaultTheme}) // Nested props declaration banned -const themeArg4 = createUseStyles(theme => ({ +const themeArg4 = createUseStyles((theme) => ({ onlyPropsAllowed: ({...props}) => ({ fontWeight: 'bold', - // @ts-expect-error propsNotAllowed: ({...innerProps}) => '' }) })) // Supplied theme type is acknowledged -const themeArg5 = createUseStyles(theme => ({})) +const themeArg5 = createUseStyles((theme) => ({})) // @ts-expect-error const themeArg5ClassesFail = themeArg5({theme: {}}) // @ts-expect-error @@ -81,7 +80,7 @@ const themeArg6ClassesFail2 = themeArg6({theme: expectedDefaultTheme}) const themeArg6ClassesPass = themeArg6({theme: expectedCustomTheme}) // Props can be determined implicitly -const themeArg7 = createUseStyles(theme => ({ +const themeArg7 = createUseStyles((theme) => ({ checkbox: ({property}: MyProps) => ({ borderColor: property }) @@ -172,53 +171,14 @@ const noThemeArg4ClassesPass2 = noThemeArg4({...expectedCustomProps, theme: expe const noThemeArg5 = createUseStyles({ singleNest: { fontWeight: 'bold', - singleValue: ({property, theme}) => '', - nestOne: ({property, theme}) => ({ + // @ts-expect-error + nestOne: ({property, theme}: MyProps & {theme: MyTheme}) => ({ color: 'red', - // @ts-expect-error - nothingAllowed: ({theme: innerTheme, ...innerProps}) => '' + display: () => 'block' }) } }) -// Nested declarations are banned (double nest test) -const noThemeArg6 = createUseStyles({ - doubleNest: { - fontWeight: 'bold', - singleValue: ({property, theme}) => '', - firstNest: { - color: 'red', - innerSingleValue: ({property, theme}) => '', - secondNest: ({property, theme}) => ({ - backgroundColor: 'blue', - // @ts-expect-error - nothingAllowed: ({theme: innerTheme, ...innerProps}) => '' - }) - } - } -}) - -// Nested declarations are banned (triple nest test) -const noThemeArg7 = createUseStyles({ - tripleNest: { - fontWeight: 'bold', - singleValue: ({property, theme}) => '', - firstNest: { - color: 'red', - innerSingleValue: ({property, theme}) => '', - secondNest: { - backgroundColor: 'blue', - innerMostSingleValue: ({property, theme}) => '', - thirdNest: ({property, theme}) => ({ - display: 'block', - // @ts-expect-error - nothingAllowed: ({theme: innerMostTheme, ...innerMostProps}) => '' - }) - } - } - } -}) - // Props can be determined implicitly const noThemeArg8 = createUseStyles({ checkbox: ({property}: MyProps) => ({ diff --git a/packages/react-jss/tests/types/docs.tsx b/packages/react-jss/tests/types/docs.tsx index 84aeb67d4..3e45d0dfa 100644 --- a/packages/react-jss/tests/types/docs.tsx +++ b/packages/react-jss/tests/types/docs.tsx @@ -8,12 +8,12 @@ type RuleNames = 'myButton' | 'myLabel' interface ButtonProps { children?: React.ReactNode spacing?: number - fontWeight?: string - labelColor?: string + fontWeight?: 'bold' + labelColor?: 'red' } interface CustomTheme { - background: string + background: 'gray' } const useStyles = createUseStyles({ diff --git a/packages/react-jss/tests/types/withStyles.tsx b/packages/react-jss/tests/types/withStyles.tsx index 0527b2341..79e46809a 100644 --- a/packages/react-jss/tests/types/withStyles.tsx +++ b/packages/react-jss/tests/types/withStyles.tsx @@ -31,7 +31,7 @@ function functionPlainObject(theme: MyTheme) { anotherClassName: { fontWeight: 'bold' } - } + } as const } ResultingComponent = withStyles(functionPlainObject)(SimpleComponent) ComponentTest = () => @@ -80,7 +80,7 @@ const plainObject = { anotherClassName: { fontWeight: 'bold' } -} +} as const ResultingComponent = withStyles(plainObject)(SimpleComponent) ComponentTest = () => diff --git a/yarn.lock b/yarn.lock index 2e35607bf..b973377bc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8140,10 +8140,10 @@ preserve@^0.2.0: resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" integrity sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks= -prettier@^1.13.5: - version "1.14.2" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.14.2.tgz#0ac1c6e1a90baa22a62925f41963c841983282f9" - integrity sha512-McHPg0n1pIke+A/4VcaS2en+pTNjy4xF+Uuq86u/5dyDO59/TtFZtQ708QIRkEZ3qwKz3GVkVa6mpxK/CpB8Rg== +prettier@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.4.0.tgz#85bdfe0f70c3e777cf13a4ffff39713ca6f64cba" + integrity sha512-DsEPLY1dE5HF3BxCRBmD4uYZ+5DCbvatnolqTqcxEgKVZnL2kUfyu7b8pPQ5+hTBkdhU9SLUmK0/pHb07RE4WQ== pretty-format@^26.6.2: version "26.6.2"