Add styled-component/native types; fix bug with children

This commit is contained in:
Jason Killian
2019-02-06 14:31:33 -05:00
parent 1b3c5640f0
commit 5dd798b9aa
5 changed files with 306 additions and 5 deletions
+6 -5
View File
@@ -4,6 +4,7 @@
// Ihor Chulinda <https://github.com/Igmat>
// Adam Lavin <https://github.com/lavoaster>
// Jessica Franco <https://github.com/Jessidhia>
// Jason Killian <https://github.com/jkillian>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// TypeScript Version: 2.9
@@ -65,7 +66,7 @@ export type StyledComponentProps<
A
> & Partial<Pick<React.ComponentPropsWithRef<C> & O, A>>,
T
>;
> & { children?: React.ReactNode };
type StyledComponentPropsWithAs<
C extends keyof JSX.IntrinsicElements | React.ComponentType<any>,
@@ -263,24 +264,24 @@ type ThemedStyledComponentFactories<T extends object> = {
[TTag in keyof JSX.IntrinsicElements]: ThemedStyledFunction<TTag, T>
};
type StyledComponentInnerComponent<
export type StyledComponentInnerComponent<
C extends React.ComponentType<any>
> = C extends
| StyledComponent<infer I, any, any, any>
| StyledComponent<infer I, any, any>
? I
: C;
type StyledComponentPropsWithRef<
export type StyledComponentPropsWithRef<
C extends keyof JSX.IntrinsicElements | React.ComponentType<any>
> = C extends AnyStyledComponent
? React.ComponentPropsWithRef<StyledComponentInnerComponent<C>>
: React.ComponentPropsWithRef<C>;
type StyledComponentInnerOtherProps<C extends AnyStyledComponent> = C extends
export type StyledComponentInnerOtherProps<C extends AnyStyledComponent> = C extends
| StyledComponent<any, any, infer O, any>
| StyledComponent<any, any, infer O>
? O
: never;
type StyledComponentInnerAttrs<
export type StyledComponentInnerAttrs<
C extends AnyStyledComponent
> = C extends StyledComponent<any, any, any, infer A> ? A : never;
+225
View File
@@ -0,0 +1,225 @@
import * as ReactNative from 'react-native'
import * as React from 'react'
import { StatelessComponent, ComponentClass } from 'react'
export {
DefaultTheme,
css,
isStyledComponent,
ThemeProps,
ThemeProvider,
ThemeConsumer,
ThemeContext,
withTheme,
} from './index';
import {
AnyStyledComponent,
StyledComponentInnerComponent,
StyledComponentInnerOtherProps,
StyledComponentInnerAttrs,
ThemedStyledFunction,
ThemedStyledInterface,
DefaultTheme
} from './index'
type AnyIfEmpty<T extends object> = keyof T extends never ? any : T;
export type ReactNativeThemedStyledFunction<
C extends React.ComponentType<any>,
T extends object,
> = ThemedStyledFunction<C, T>;
// Copied over from "ThemedBaseStyledInterface" in index.d.ts in order to remove DOM element typings
interface ReactNativeThemedBaseStyledInterface<T extends object> {
<C extends AnyStyledComponent>(component: C): ThemedStyledFunction<
StyledComponentInnerComponent<C>,
T,
StyledComponentInnerOtherProps<C>,
StyledComponentInnerAttrs<C>
>;
<C extends React.ComponentType<any>>(
// unfortunately using a conditional type to validate that it can receive a `theme?: Theme`
// causes tests to fail in TS 3.1
component: C
): ThemedStyledFunction<C, T>;
}
type ReactNativeThemedStyledInterface<T extends object> = ReactNativeThemedBaseStyledInterface<
AnyIfEmpty<T>
>;
export interface ReactNativeStyledInterface<T extends object> extends ReactNativeThemedStyledInterface<T> {
ActivityIndicator: ReactNativeThemedStyledFunction<
typeof ReactNative.ActivityIndicator,
T
>;
ActivityIndicatorIOS: ReactNativeThemedStyledFunction<
typeof ReactNative.ActivityIndicator,
T
>;
Button: ReactNativeThemedStyledFunction<
typeof ReactNative.Button,
T
>;
DatePickerIOS: ReactNativeThemedStyledFunction<
typeof ReactNative.DatePickerIOS,
T
>;
DrawerLayoutAndroid: ReactNativeThemedStyledFunction<
typeof ReactNative.DrawerLayoutAndroid,
T
>;
Image: ReactNativeThemedStyledFunction<
typeof ReactNative.Image,
T
>;
ImageBackground: ReactNativeThemedStyledFunction<
typeof ReactNative.ImageBackground,
T
>;
KeyboardAvoidingView: ReactNativeThemedStyledFunction<
typeof ReactNative.KeyboardAvoidingView,
T
>;
ListView: ReactNativeThemedStyledFunction<
typeof ReactNative.ListView,
T
>;
MapView: ReactNativeThemedStyledFunction<
typeof ReactNative.MapView,
T
>;
Modal: ReactNativeThemedStyledFunction<
typeof ReactNative.Modal,
T
>;
NavigatorIOS: ReactNativeThemedStyledFunction<
typeof ReactNative.NavigatorIOS,
T
>;
Picker: ReactNativeThemedStyledFunction<
typeof ReactNative.Picker,
T
>;
PickerIOS: ReactNativeThemedStyledFunction<
typeof ReactNative.PickerIOS,
T
>;
ProgressBarAndroid: ReactNativeThemedStyledFunction<
typeof ReactNative.ProgressBarAndroid,
T
>;
ProgressViewIOS: ReactNativeThemedStyledFunction<
typeof ReactNative.ProgressViewIOS,
T
>;
ScrollView: ReactNativeThemedStyledFunction<
typeof ReactNative.ScrollView,
T
>;
SegmentedControlIOS: ReactNativeThemedStyledFunction<
typeof ReactNative.SegmentedControlIOS,
T
>;
Slider: ReactNativeThemedStyledFunction<
typeof ReactNative.Slider,
T
>;
SliderIOS: ReactNativeThemedStyledFunction<
typeof ReactNative.Slider,
T
>;
SnapshotViewIOS: ReactNativeThemedStyledFunction<
typeof ReactNative.SnapshotViewIOS,
T
>;
Switch: ReactNativeThemedStyledFunction<
typeof ReactNative.Switch,
T
>;
RecyclerViewBackedScrollView: ReactNativeThemedStyledFunction<
typeof ReactNative.RecyclerViewBackedScrollView,
T
>;
RefreshControl: ReactNativeThemedStyledFunction<
typeof ReactNative.RefreshControl,
T
>;
SafeAreaView: ReactNativeThemedStyledFunction<
typeof ReactNative.SafeAreaView,
T
>;
StatusBar: ReactNativeThemedStyledFunction<
typeof ReactNative.StatusBar,
T
>;
SwipeableListView: ReactNativeThemedStyledFunction<
typeof ReactNative.SwipeableListView,
T
>
SwitchAndroid: ReactNativeThemedStyledFunction<
typeof ReactNative.Switch,
T
>;
SwitchIOS: ReactNativeThemedStyledFunction<
typeof ReactNative.SwitchIOS,
T
>;
TabBarIOS: ReactNativeThemedStyledFunction<
typeof ReactNative.TabBarIOS,
T
>;
Text: ReactNativeThemedStyledFunction<
typeof ReactNative.Text,
T
>;
TextInput: ReactNativeThemedStyledFunction<
typeof ReactNative.TextInput,
T
>;
ToolbarAndroid: ReactNativeThemedStyledFunction<
typeof ReactNative.ToolbarAndroid,
T
>;
TouchableHighlight: ReactNativeThemedStyledFunction<
typeof ReactNative.TouchableHighlight,
T
>;
TouchableNativeFeedback: ReactNativeThemedStyledFunction<
typeof ReactNative.TouchableNativeFeedback,
T
>;
TouchableOpacity: ReactNativeThemedStyledFunction<
typeof ReactNative.TouchableOpacity,
T
>;
TouchableWithoutFeedback: ReactNativeThemedStyledFunction<
typeof ReactNative.TouchableWithoutFeedback,
T
>;
View: ReactNativeThemedStyledFunction<
typeof ReactNative.View,
T
>;
ViewPagerAndroid: ReactNativeThemedStyledFunction<
typeof ReactNative.ViewPagerAndroid,
T
>;
WebView: ReactNativeThemedStyledFunction<
typeof ReactNative.WebView,
T
>;
FlatList: ReactNativeThemedStyledFunction<
typeof ReactNative.FlatList,
T
>;
SectionList: ReactNativeThemedStyledFunction<
typeof ReactNative.SectionList,
T
>;
}
declare const styled: ReactNativeStyledInterface<DefaultTheme>;
export default styled;
+15
View File
@@ -1001,3 +1001,18 @@ function validateDefaultProps() {
<OtherStyledComponent requiredProp="1" />; // $ExpectError
}
// failing example from https://github.com/DefinitelyTyped/DefinitelyTyped/issues/31491#issuecomment-459353227
interface WrapperClassProps {
className?: string
}
export class WrapperClassComponent extends React.Component<WrapperClassProps> {
render() {
return <div className={this.props.className}>{this.props.children}</div>
}
}
const WrapperClass = styled(WrapperClassComponent)`
border: 1px solid grey;
`
const wrapperClass = <WrapperClass>Text</WrapperClass>
+58
View File
@@ -0,0 +1,58 @@
import * as React from "react";
import * as ReactNative from "react-native";
import * as ReactDOMServer from "react-dom/server";
import styled, {
css,
isStyledComponent,
ThemeProps,
ThemeProvider,
withTheme,
ThemeConsumer,
} from "styled-components/native";
import {} from "styled-components/cssprop";
const StyledView = styled.View`
background-color: papayawhip;
`
const StyledText = styled(ReactNative.Text)`
color: palevioletred;
`
class MyReactNativeComponent extends React.Component {
render() {
return (
<StyledView collapsable>
<StyledText adjustsFontSizeToFit>Hello World!</StyledText>
</StyledView>
)
}
}
const invalidProp = <StyledText randoName={2} />; // $ExpectError
const invalidTag = styled.div` margin-top: 5px; `; // $ExpectError
interface MyTheme {
primary: string;
}
interface ButtonProps {
name: string;
primary?: boolean;
theme: MyTheme;
}
class MyButton extends React.Component<ButtonProps> {
render() {
return <ReactNative.TouchableOpacity>Custom button</ReactNative.TouchableOpacity>;
}
}
const TomatoButton = styled(MyButton)`
color: tomato;
border-color: tomato;
`;
// needs name prop, but not theme prop
const tomatoElement = <TomatoButton name="needed" />
+2
View File
@@ -20,9 +20,11 @@
},
"files": [
"index.d.ts",
"native.d.ts",
"macro.d.ts",
"cssprop.d.ts",
"test/index.tsx",
"test/native.tsx",
"test/macro.tsx"
]
}