Skip to content

Commit

Permalink
fix: typings for additional props (#622)
Browse files Browse the repository at this point in the history
  • Loading branch information
Anber committed Jul 14, 2020
1 parent 6a99427 commit f41f226
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 30 deletions.
6 changes: 6 additions & 0 deletions src/StyledMeta.ts
@@ -0,0 +1,6 @@
export type StyledMeta = {
__linaria: {
className: string;
extends: StyledMeta;
};
};
2 changes: 1 addition & 1 deletion src/babel/evaluators/templateProcessor.ts
Expand Up @@ -10,7 +10,7 @@ import generator from '@babel/generator';

import { units } from '../units';
import { State, StrictOptions, TemplateExpression, ValueCache } from '../types';
import { StyledMeta } from '../../react/styled';
import { StyledMeta } from '../../StyledMeta';

import isSerializable from '../utils/isSerializable';
import { debug } from '../utils/logger';
Expand Down
2 changes: 1 addition & 1 deletion src/babel/types.ts
@@ -1,6 +1,6 @@
import { types as t, TransformOptions } from '@babel/core';
import { NodePath } from '@babel/traverse';
import { StyledMeta } from '../react/styled';
import { StyledMeta } from '../StyledMeta';

export type JSONValue = string | number | boolean | JSONObject | JSONArray;

Expand Down
4 changes: 2 additions & 2 deletions src/core/css.ts
@@ -1,12 +1,12 @@
type CSSMeta = string;
import { StyledMeta } from '../StyledMeta';

type CSSProperties = {
[key: string]: string | number | CSSProperties;
};

export default function css(
_strings: TemplateStringsArray,
..._exprs: Array<string | number | CSSProperties | CSSMeta>
..._exprs: Array<string | number | CSSProperties | StyledMeta>
): string {
throw new Error(
'Using the "css" tag in runtime is not supported. Make sure you have set up the Babel plugin correctly.'
Expand Down
25 changes: 12 additions & 13 deletions src/react/styled.ts
Expand Up @@ -7,13 +7,7 @@
import * as React from 'react'; // eslint-disable-line import/no-extraneous-dependencies
import validAttr from '@emotion/is-prop-valid';
import { cx } from '../index';

export type StyledMeta = {
__linaria: {
className: string;
extends: StyledMeta;
};
};
import { StyledMeta } from '../StyledMeta';

type Options = {
name: string;
Expand Down Expand Up @@ -170,16 +164,21 @@ type HtmlStyledTag<TName extends keyof JSX.IntrinsicElements> = <
) => StyledComponent<JSX.IntrinsicElements[TName] & TAdditionalProps>;

type ComponentStyledTag<T> = <
Props = T extends React.FunctionComponent<infer TProps> ? TProps : T
OwnProps = {},
TrgProps = T extends React.FunctionComponent<infer TProps> ? TProps : T
>(
strings: TemplateStringsArray,
// Expressions can contain functions only if wrapped component has style property
...exprs: Props extends { style?: React.CSSProperties }
? Array<StaticPlaceholder | ((props: Props) => string | number)>
...exprs: TrgProps extends { style?: React.CSSProperties }
? Array<
StaticPlaceholder | ((props: OwnProps & TrgProps) => string | number)
>
: StaticPlaceholder[]
) => T extends React.FunctionComponent<any>
? StyledMeta & T
: StyledComponent<Props>;
) => keyof OwnProps extends never
? T extends React.FunctionComponent<any>
? StyledMeta & T
: StyledComponent<TrgProps>
: StyledComponent<OwnProps & TrgProps>;

type StyledJSXIntrinsics = {
readonly [P in keyof JSX.IntrinsicElements]: HtmlStyledTag<P>;
Expand Down
48 changes: 35 additions & 13 deletions types/styled.ts
Expand Up @@ -84,16 +84,38 @@ styled.a`
}
`({ href: 'about:blank' });

// Issue #536
const Title = styled.div<{ background: string }>`
background: ${props => props.background};
`;

// $ExpectType "extends"
isExtends<typeof Title, React.FC<{ background: string }>>();

css`
${Title} {
color: green;
}
`;
((/* Issue #536 */) => {
const Title = styled.div<{ background: string }>`
background: ${props => props.background};
`;

// $ExpectType "extends"
isExtends<typeof Title, React.FC<{ background: string }>>();

css`
${Title} {
color: green;
}
`;
})();

((/* Issue #622 */) => {
const Wrapper = styled.div<{ prop1: boolean }>`
width: 1em;
background-color: ${props => (props.prop1 ? 'transparent' : 'green')};
`;

const styledTag = styled(Wrapper);

const NewWrapper = styledTag<{ prop2: string }>`
width: 2em;
background-color: ${props => (props.prop1 ? 'transparent' : 'red')};
color: ${props => props.prop2};
`;

// $ExpectType Validator<boolean> | undefined
NewWrapper.propTypes!.prop1;

// $ExpectType Validator<string> | undefined
NewWrapper.propTypes!.prop2;
})();

0 comments on commit f41f226

Please sign in to comment.