Skip to content

Commit fae497e

Browse files
committed
feat: support generic props
1 parent 40a8ca9 commit fae497e

File tree

4 files changed

+87
-14
lines changed

4 files changed

+87
-14
lines changed

eslint.config.mjs

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,27 @@
11
import antfu from '@antfu/eslint-config'
22

3-
export default antfu({
4-
markdown: false,
5-
ignores: ['**/node_modules/**', '**/dist/**', '**/build/**', '**/coverage/**'],
6-
})
3+
export default antfu(
4+
{
5+
markdown: false,
6+
ignores: [
7+
'**/node_modules/**',
8+
'**/dist/**',
9+
'**/build/**',
10+
'**/coverage/**',
11+
],
12+
},
13+
{
14+
files: ['packages/plugins/typescript-syntax/**/*.ts'],
15+
rules: {
16+
'no-unused-vars': 'off',
17+
'no-cond-assign': 'warn',
18+
'no-console': 'warn',
19+
'unused-imports/no-unused-vars': 'warn',
20+
'regexp/no-unused-capturing-group': 'warn',
21+
'style/max-statements-per-line': 'warn',
22+
'regexp/no-super-linear-backtracking': 'warn',
23+
'unicorn/prefer-number-properties': 'warn',
24+
'style/no-mixed-operators': 'warn',
25+
},
26+
},
27+
)

packages/core/src/styled.ts

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,17 @@ interface StyledComponent<T extends object> {
3434
<P>(
3535
styles: TemplateStringsArray,
3636
...expressions: (
37-
| ExpressionType<BaseContext<P & ExtractPropTypes<PropsDefinition<T>>>>
38-
| ExpressionType<BaseContext<P & ExtractPropTypes<PropsDefinition<T>>>>[]
37+
| ExpressionType<BaseContext<P & T>>
38+
| ExpressionType<BaseContext<P & T>>[]
3939
)[]
40-
): DefineSetupFnComponent<{ as?: string, props?: P } & ExtractPropTypes<PropsDefinition<T>> & HTMLAttributes>
40+
): DefineSetupFnComponent<{ as?: string, props?: P } & ExtractPropTypes<PropsDefinition<T & P>> & HTMLAttributes>
4141

4242
attrs: <A = object>(
43-
attrs: A | ((props: ExtractPropTypes<PropsDefinition<T>>) => A),
43+
attrs: object | ((props: PropsDefinition<T> & A) => object),
4444
) => StyledComponent<A & ExtractPropTypes<PropsDefinition<T>>>
45+
46+
// 支持泛型参数的类型定义
47+
<P extends object>(props: PropsDefinition<P>): StyledComponent<P & T>
4548
}
4649

4750
function baseStyled<T extends object>(target: string | InstanceType<any>, propsDefinition?: PropsDefinition<T>): StyledComponent<T> {
@@ -50,17 +53,25 @@ function baseStyled<T extends object>(target: string | InstanceType<any>, propsD
5053
}
5154
let defaultAttrs: unknown
5255
function styledComponent<P>(
53-
styles: TemplateStringsArray,
56+
stylesOrProps: TemplateStringsArray | PropsDefinition<P>,
5457
...expressions: (
5558
| ExpressionType<BaseContext<P & ExtractPropTypes<PropsDefinition<T>>>>
5659
| ExpressionType<BaseContext<P & ExtractPropTypes<PropsDefinition<T>>>>[]
5760
)[]
5861
) {
59-
const cssStringsWithExpression = insertExpressions(styles, expressions)
62+
// 处理泛型参数的情况,如 styled.div<Props>
63+
if (!Array.isArray(stylesOrProps)) {
64+
return baseStyled(target, { ...propsDefinition, ...stylesOrProps } as PropsDefinition<T & P>) as StyledComponent<T & P>
65+
}
66+
67+
// 正常的样式模板字符串处理
68+
const cssStringsWithExpression = insertExpressions(stylesOrProps as TemplateStringsArray, expressions)
6069
return createStyledComponent<P>(cssStringsWithExpression)
6170
}
6271

63-
styledComponent.attrs = function <A extends object>(attrs: A) {
72+
styledComponent.attrs = function <A = object>(
73+
attrs: object | ((props: ExtractPropTypes<PropsDefinition<T>> & A) => object),
74+
) {
6475
defaultAttrs = attrs
6576
return styledComponent
6677
}
@@ -174,11 +185,14 @@ function baseStyled<T extends object>(target: string | InstanceType<any>, propsD
174185
return styledComponent as StyledComponent<T>
175186
}
176187

177-
/** Append all the supported HTML elements to the styled properties */
178-
const styled = baseStyled as typeof baseStyled & {
179-
[E in SupportedHTMLElements]: ReturnType<typeof baseStyled>
188+
// 为styled添加attrs方法的类型定义
189+
type StyledInterface = typeof baseStyled & {
190+
[E in SupportedHTMLElements]: StyledComponent<object>
180191
}
181192

193+
/** Append all the supported HTML elements to the styled properties */
194+
const styled = baseStyled as StyledInterface
195+
182196
domElements.forEach((domElement: SupportedHTMLElements) => {
183197
styled[domElement] = baseStyled(domElement)
184198
})

packages/playground/src/App.vue

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,37 @@ const Container = styled.div`
2727
color: #fff;
2828
}
2929
`
30+
31+
const StyledDiv = styled.div<{
32+
color: string
33+
}>`
34+
color: ${(props) => props.color || 'white'};
35+
`
36+
37+
type StyledDivProps = {
38+
color: string
39+
}
40+
41+
const StyledDiv2 = styled.div<StyledDivProps>`
42+
color: ${(props) => props.color || 'white'};
43+
`
44+
45+
type StyledDiv3Props = {
46+
size: number
47+
} & StyledDivProps
48+
49+
const StyledDiv3 = styled.div<StyledDiv3Props>`
50+
color: ${(props) => props.color || 'white'};
51+
font-size: ${(props) => props.size}px;
52+
`
53+
54+
const StyledInput = styled.input.attrs<{color: string, inputType: string}>((props) => ({
55+
type: props.inputType,
56+
}))`
57+
background: ${(props) => props.color};
58+
color: blue;
59+
`
60+
3061
</script>
3162

3263
<template>
@@ -45,6 +76,11 @@ const Container = styled.div`
4576
<Container>
4677
<Button>888</Button>
4778
</Container>
79+
80+
<StyledDiv color="red">999</StyledDiv>
81+
<StyledDiv2 color="red">999</StyledDiv2>
82+
<StyledDiv3 color="red" :size="100">999</StyledDiv3>
83+
<StyledInput color="red" input-type="password" />
4884
</ThemeProvider>
4985
</template>
5086

packages/playground/vite.config.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import vue from '@vitejs/plugin-vue'
22
import vueJsx from '@vitejs/plugin-vue-jsx'
33
import { defineConfig } from 'vite'
4+
import p from '../plugins/typescript-syntax/index'
45

56
// https://vitejs.dev/config/
67
export default defineConfig({
@@ -9,6 +10,7 @@ export default defineConfig({
910
extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue', '.less'],
1011
},
1112
plugins: [
13+
p(),
1214
vue({
1315
script: {
1416
defineModel: true,

0 commit comments

Comments
 (0)