From d08aba397844405c08995fe0728d0d9c82ccf512 Mon Sep 17 00:00:00 2001 From: Jessica Date: Mon, 3 Dec 2018 20:11:17 +0900 Subject: [PATCH] Fix overly permissible first argument to css, styled() and createGlobalStyle --- types/styled-components/index.d.ts | 38 +++++------ types/styled-components/test/index.tsx | 91 ++++++++++++++++++++++++-- 2 files changed, 103 insertions(+), 26 deletions(-) diff --git a/types/styled-components/index.d.ts b/types/styled-components/index.d.ts index 2f6fa61317..ca3ff22c0e 100644 --- a/types/styled-components/index.d.ts +++ b/types/styled-components/index.d.ts @@ -73,7 +73,7 @@ export type SimpleInterpolation = | InterpolationValue | FlattenSimpleInterpolation; // must be an interface to be self-referential -interface FlattenSimpleInterpolation +export interface FlattenSimpleInterpolation extends ReadonlyArray {} export type InterpolationFunction

= (props: P) => Interpolation

; @@ -176,10 +176,9 @@ export interface ThemedStyledFunctionBase< ( first: | TemplateStringsArray - | NonNullable< - Interpolation< - ThemedStyledProps & O, T> - > + | CSSObject + | InterpolationFunction< + ThemedStyledProps & O, T> >, ...rest: Array< Interpolation< @@ -187,17 +186,12 @@ export interface ThemedStyledFunctionBase< > > ): StyledComponent; - // at least the first argument is required, whatever it is ( first: | TemplateStringsArray - | NonNullable< - Interpolation< - ThemedStyledProps< - StyledComponentPropsWithRef & O & U, - T - > - > + | CSSObject + | InterpolationFunction< + ThemedStyledProps & O & U, T> >, ...rest: Array< Interpolation< @@ -288,19 +282,21 @@ export type StyledInterface = ThemedStyledInterface; export interface BaseThemedCssFunction { ( - first: TemplateStringsArray | NonNullable, + first: TemplateStringsArray | CSSObject, ...interpolations: SimpleInterpolation[] ): FlattenSimpleInterpolation; ( first: | TemplateStringsArray - | NonNullable>>, + | CSSObject + | InterpolationFunction>, ...interpolations: Array>> ): FlattenInterpolation>;

( first: | TemplateStringsArray - | NonNullable>>, + | CSSObject + | InterpolationFunction>, ...interpolations: Array>> ): FlattenInterpolation>; } @@ -333,7 +329,8 @@ export interface ThemedStyledComponentsModule< createGlobalStyle

( first: | TemplateStringsArray - | NonNullable>>, + | CSSObject + | InterpolationFunction>, ...interpolations: Array>> ): GlobalStyleComponent; @@ -405,7 +402,8 @@ export function keyframes( export function createGlobalStyle

( first: | TemplateStringsArray - | NonNullable>>, + | CSSObject + | InterpolationFunction>, ...interpolations: Array>> ): GlobalStyleComponent; @@ -468,7 +466,7 @@ export class StyleSheetManager extends React.Component< */ // ONLY string literals and inline invocations of css`` are supported, anything else crashes the plugin export type CSSProp> = - string | - FlattenInterpolation>; + | string + | FlattenInterpolation>; export default styled; diff --git a/types/styled-components/test/index.tsx b/types/styled-components/test/index.tsx index 2d70f74106..d382b42628 100644 --- a/types/styled-components/test/index.tsx +++ b/types/styled-components/test/index.tsx @@ -14,7 +14,10 @@ import styled, { withTheme, ThemeConsumer, StyledComponent, - ThemedStyledComponentsModule + ThemedStyledComponentsModule, + FlattenSimpleInterpolation, + SimpleInterpolation, + FlattenInterpolation } from "styled-components"; import {} from "styled-components/cssprop"; @@ -101,13 +104,13 @@ const fadeIn = keyframes` `; const showAnimation = css` - opacity: 1; - transform: scale(1) translateY(0); + opacity: 1; + transform: scale(1) translateY(0); `; const hideAnimation = css` - opacity: 0; - transform: scale(0.95, 0.8) translateY(20px); + opacity: 0; + transform: scale(0.95, 0.8) translateY(20px); `; const entryAnimation = keyframes` @@ -694,6 +697,8 @@ async function typedThemes() { return props.theme.color; }}; `; + // can't use a FlattenInterpolation as the first argument, would make broken css + // $ExpectError const ThemedDiv4 = styled.div(themedCss); const themedCssWithNesting = css(props => ({ @@ -714,7 +719,6 @@ async function typedThemes() { - {theme => { // $ExpectType string @@ -867,3 +871,78 @@ function cssProp() { ); } + +function validateArgumentsAndReturns() { + const t1: FlattenSimpleInterpolation[] = [ + css({ color: "blue" }), + css` + color: blue; + `, + css` + color: ${"blue"}; + ` + ]; + const t4: FlattenInterpolation = [ + css` + color: ${() => "blue"}; + `, + css(() => ({ color: "blue" })), + css( + () => + css` + color: "blue"; + ` + ) + ]; + + // if the first argument is array-like it's always treated as a string[], this breaks things + css( + // $ExpectError + css` + ${{ color: "blue" }} + ` + ); + // _technically_ valid as styled-components doesn't look at .raw but best not to support it + // $ExpectError + css([]); + + styled.div({ color: "blue" }); + styled.div(props => ({ color: props.theme.color })); + styled.div` + color: ${"blue"}; + `; + // These don't work for the same reason css doesn't work + styled.div( + // $ExpectError + css` + ${{ color: "blue" }} + ` + ); + // $ExpectError + styled.div([]); + + createGlobalStyle({ + ":root": { + color: "blue" + } + }); + createGlobalStyle` + :root { + color: blue; + } + `; + createGlobalStyle(() => ({ + ":root": { + color: "blue" + } + })); + // these are invalid for the same reason as in styled.div + // $ExpectError + createGlobalStyle(css` + :root { + color: ${() => "blue"}; + } + `); + // $ExpectError + createGlobalStyle([]); +}