Skip to content

Commit

Permalink
🐛 fix: 修正 createStyles 类型不正确的问题
Browse files Browse the repository at this point in the history
  • Loading branch information
arvinxx committed Jan 10, 2023
1 parent e0fa055 commit bacdc0b
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 36 deletions.
10 changes: 3 additions & 7 deletions src/functions/createStyish.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,17 @@
import { ReturnStyleToUse } from '@/types';
import { ReturnStyleToUse, StyleInputType } from '@/types';
import { createStyles, StyleOrGetStyleFn } from './createStyles';

/**
* 业务应用中创建复合通用样式的进阶
*/
export function createStylish<Props, Styles>(
cssStyleOrGetCssStyleFn: StyleOrGetStyleFn<Props, Styles>,
export function createStylish<Props, Styles extends StyleInputType>(
cssStyleOrGetCssStyleFn: StyleOrGetStyleFn<Styles, Props>,
) {
// FIXME :类型定义
// @ts-ignore
const useStyles = createStyles(cssStyleOrGetCssStyleFn);

return (props?: Props): ReturnStyleToUse<Styles> => {
const { styles } = useStyles(props);

// FIXME :类型定义
// @ts-ignore
return styles;
};
}
36 changes: 20 additions & 16 deletions src/functions/createStyles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
FullStylish,
FullToken,
ReturnStyleToUse,
StyleDefinition,
StyleInputType,
Theme,
ThemeAppearance,
} from '@/types';
Expand All @@ -22,41 +22,45 @@ export interface CreateStylesTheme extends CommonStyleUtils {
/**
* 最终返回 styles 对象的类型定义
*/
export interface ReturnStyles<Obj> {
styles: ReturnStyleToUse<Obj>;
export interface ReturnStyles<T extends StyleInputType> {
styles: ReturnStyleToUse<T>;
theme: Theme;
cx: Emotion['cx'];
}

// 获取样式
export type GetStyleFn<Input> = <P>(theme: CreateStylesTheme, props?: P) => StyleDefinition<Input>;
export type GetStyleFn<Input extends StyleInputType, Props> = <P extends Props>(
theme: CreateStylesTheme,
props?: P,
) => Input;

/**
* 创建样式的函数或者对象
*/
export type StyleOrGetStyleFn<Input> = Input extends (...args: any[]) => any
? StyleDefinition<Input>
: GetStyleFn<Input>;
export type StyleOrGetStyleFn<Input extends StyleInputType, Props> =
| Input
| GetStyleFn<Input, Props>;

/**
* 业务应用中创建样式基础写法
*/
export const createStyles =
<Input>(styleOrGetStyleFn: StyleOrGetStyleFn<Input>) =>
<P>(props?: P): ReturnStyles<Input> => {
<Props, Input extends StyleInputType>(styleOrGetStyleFn: StyleOrGetStyleFn<Input, Props>) =>
(props?: Props): ReturnStyles<Input> => {
const theme = useTheme();

// FIXME:如何收敛类型? How to fix types?
// @ts-ignore
return useMemo<ReturnStyles<Input>>(() => {
let styles;
return useMemo(() => {
let styles: ReturnStyleToUse<Input>;

if (styleOrGetStyleFn instanceof Function) {
const { stylish, appearance, ...token } = theme;

styles = styleOrGetStyleFn({ token, stylish, appearance, cx, css, injectGlobal }, props);
styles = styleOrGetStyleFn(
{ token, stylish, appearance, cx, css, injectGlobal },
props,
) as any;
} else {
styles = styleOrGetStyleFn;
styles = styleOrGetStyleFn as any;
}

if (typeof styles === 'object') {
Expand All @@ -68,7 +72,7 @@ export const createStyles =

return [key, value];
}),
);
) as any;
}

return {
Expand Down
30 changes: 17 additions & 13 deletions src/types/genericUtils.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,28 @@
import { CSSObject } from '@emotion/css';

type CSSParams<T> = T extends string ? string : CSSObject;
type StyleObject = Record<string, CSSObject | string>;

/**
* 给用户提供类型定义的返回签名
* 用户可以使用 key: css` color:red `,或者 key :{ color : 'red' },都能正常提供类型定义
* 所有用户的可能的入参类型
*/
export type StyleDefinition<Style> = Style extends string
? string
: {
[Key in keyof Style]: CSSParams<Style[Key]>;
};
export type StyleInputType = string | CSSObject | StyleObject;

type StyleObjectOnly<T extends StyleInputType> = T extends string ? never : T;

/**
* 根据用户输入的样式对象,导出可以给用户使用消费的类型泛型
* 譬如用户输入为 { a: css`color: red;`, b: { color: 'red' }
* 输出的类型泛型为 { a:string; b:string }
*/
type DefinitionToResult<T, K extends keyof T = keyof T> = {
[P in K]: string;
};

/**
* 根据用户返回的样式对象,返回一个可以给用户使用的
* 譬如用户输入为 { a: css`color: red;`, b: { color: 'red' }
* 输出的类型泛型为 { a:string; b:string }
*/
export type ReturnStyleToUse<T> = T extends string
? string
: {
[Key in keyof T]: string;
};
export type ReturnStyleToUse<T extends StyleInputType> = T extends string
? T
: DefinitionToResult<StyleObjectOnly<T>>;

0 comments on commit bacdc0b

Please sign in to comment.