Merge pull request #33341 from flavordaaave/master

Added interface to re-export module with theme interface
This commit is contained in:
Jessica Franco
2019-03-06 13:48:20 +09:00
committed by GitHub
3 changed files with 166 additions and 5 deletions

View File

@@ -6,6 +6,7 @@
// Jessica Franco <https://github.com/Jessidhia>
// Jason Killian <https://github.com/jkillian>
// Sebastian Silbermann <https://github.com/eps1lon>
// David Ruisinger <https://github.com/flavordaaave>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// TypeScript Version: 2.9

View File

@@ -2,24 +2,28 @@ import * as ReactNative from 'react-native';
import * as React from 'react';
export {
DefaultTheme,
css,
DefaultTheme,
isStyledComponent,
ThemeProps,
ThemeProvider,
ThemeConsumer,
ThemeContext,
ThemeProps,
ThemeProvider,
withTheme,
} from './index';
import {
AnyStyledComponent,
DefaultTheme,
isStyledComponent,
StyledComponentInnerAttrs,
StyledComponentInnerComponent,
StyledComponentInnerOtherProps,
StyledComponentInnerAttrs,
ThemedCssFunction,
ThemedStyledFunction,
ThemedStyledInterface,
DefaultTheme
ThemeProviderComponent,
WithThemeFnInterface
} from './index';
type AnyIfEmpty<T extends object> = keyof T extends never ? any : T;
@@ -211,6 +215,23 @@ export interface ReactNativeStyledInterface<T extends object> extends ReactNativ
>;
}
export interface ReactNativeThemedStyledComponentsModule<
T extends object,
U extends object = T
> {
default: ReactNativeStyledInterface<T>;
css: ThemedCssFunction<T>;
withTheme: WithThemeFnInterface<T>;
ThemeProvider: ThemeProviderComponent<T, U>;
ThemeConsumer: React.Consumer<T>;
ThemeContext: React.Context<T>;
// This could be made to assert `target is StyledComponent<any, T>` instead, but that feels not type safe
isStyledComponent: typeof isStyledComponent;
}
declare const styled: ReactNativeStyledInterface<DefaultTheme>;
export default styled;

View File

@@ -9,6 +9,7 @@ import styled, {
ThemeProvider,
withTheme,
ThemeConsumer,
ReactNativeThemedStyledComponentsModule,
} from "styled-components/native";
import {} from "styled-components/cssprop";
@@ -57,3 +58,141 @@ const TomatoButton = styled(MyButton)`
// needs name prop, but not theme prop
const tomatoElement = <TomatoButton name="needed" />;
async function typedThemes() {
const theme = {
color: "green"
};
// abuse "await import(...)" to be able to reference the styled-components namespace
// without actually doing a top level namespace import
const {
default: styled,
css,
ThemeProvider,
ThemeConsumer
} = (await import("styled-components/native")) as any as ReactNativeThemedStyledComponentsModule<
typeof theme
>;
const ThemedView = styled.View`
background: ${props => {
// $ExpectType string
props.theme.color;
// $ExpectType string | undefined
props.testID;
return props.theme.color;
}};
`;
const ThemedView2 = styled.View(props => {
// $ExpectType string
props.theme.color;
// $ExpectType string | undefined
props.testID;
return {
background: props.theme.color
};
});
const ThemedView3 = styled.View(props => {
// $ExpectType string
props.theme.color;
// $ExpectType string | undefined
props.testID;
return css`
background: ${props.theme.color};
`;
});
const themedCss = css`
background: ${props => {
// $ExpectType string
props.theme.color;
// $ExpectType "theme"
type Keys = keyof typeof props;
return props.theme.color;
}};
`;
// can't use a FlattenInterpolation as the first argument, would make broken css
// $ExpectError
const ThemedView4 = styled.View(themedCss);
const themedCssWithNesting = css(props => ({
color: props.theme.color,
[ThemedView3]: {
color: "green"
}
}));
return (
<ThemeProvider theme={theme}>
<>
<ThemedView />
<ThemedView2 />
<ThemedView3 />
<ThemeConsumer>
{theme => {
// $ExpectType string
theme.color;
return theme.color;
}}
</ThemeConsumer>
</>
</ThemeProvider>
);
}
async function reexportCompatibility() {
const sc = await import("styled-components/native");
const themed = sc as ReactNativeThemedStyledComponentsModule<any>;
let { ...scExports } = sc;
let { ...themedExports } = themed;
// both branches must be assignable to each other
if (Math.random()) {
scExports = themedExports;
} else {
themedExports = scExports;
}
}
async function themeAugmentation() {
interface BaseTheme {
background: string;
}
interface ExtraTheme extends BaseTheme {
accent: string;
}
const base = (await import("styled-components/native")) as any as ReactNativeThemedStyledComponentsModule<
BaseTheme
>;
const extra = (await import("styled-components/native")) as any as ReactNativeThemedStyledComponentsModule<
ExtraTheme,
BaseTheme
>;
return (
<base.ThemeProvider
theme={{
background: "black"
}}
>
<>
<extra.ThemeProvider
theme={base => base} // $ExpectError
>
<extra.ThemeConsumer>{() => null}</extra.ThemeConsumer>
</extra.ThemeProvider>
<extra.ThemeProvider
theme={base => ({
...base,
accent: "blue"
})}
>
<extra.ThemeConsumer>{() => null}</extra.ThemeConsumer>
</extra.ThemeProvider>
</>
</base.ThemeProvider>
);
}