reactjs - Styled-components กับ Typescript: ขาดชนิดสำหรับตัวแปรธีม
ตัวแปร theme ได้ชนิด any เพียงในระดับบนสุดเท่านั้น ถ้าฉันใช้ theme ในบล็อก css'' มันจะได้การพิมพ์ที่ถูกต้อง DefaultTheme
ตัวอย่าง :
const Header = styled.div<{ invertedColor: boolean }>`
color: ${({ theme }) => theme.color.blue}; // theme = any
${({ invertedColor }) =>
invertedColor &&
css`
color: ${({ theme }) => theme.color.white}; // theme = DefaultTheme (correct)
`}
`
นอกจากนี้ <{ invertedColor: boolean }> ก็ไม่ทำงานเนื่องจาก invertedColor เป็น any ที่นี่
ฉันได้เพิ่ม styled-components.d.ts พร้อมกับเนื้อหาดังต่อไปนี้:
import 'styled-components';
type ColorType = 'blue' | 'white';
declare module 'styled-components' {
export interface DefaultTheme {
color: Record<ColorType, string>;
}
}
โดยใช้เวอร์ชันดังต่อไปนี้:
"@types/styled-components": "^5.1.22",
"styled-components": "^5.3.3",
ฉันได้พยายามดีบั๊กและตรวจสอบว่าประเภทหายไปที่ไหน เพราะมันถูกส่งไปอย่างถูกต้องที่ ThemeProvider - และยังได้ลองใช้ทุกวิธีแก้ปัญหาจากที่นี่ด้วย: https://github.com/styled-components/styled-components/issues/1589
วิธีที่ดีที่สุดในการดีบั๊กเรื่องนั้นคืออะไร มีคำใบ้ไหม?
คำตอบ #1
แปลกที่คุณกำลังมี any สำหรับการพิมพ์ธีมของคุณ
ฉันกำลังทำมันในวิธีที่ใกล้เคียงแต่ต่างออกไป:
styled-component.d.ts// import original module declarations
import 'styled-components';
import { ITheme } from './styles/theme';
// and extend them!
declare module 'styled-components' {
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface DefaultTheme extends ITheme {}
}
ฉันกำลังขยาย DefaultTheme ด้วยวัตถุ ITheme ของฉัน ซึ่งเป็นบางสิ่งที่มีลักษณะประมาณนี้:
import {
borderRadius,
boxShadows,
IBorderRadius,
IBoxShadows,
ITransitions,
IZIndexes,
transitions,
zIndexes,
} from './base';
import { colors, IColors } from './colors';
import { ISizes, sizes } from './sizes';
export interface ITheme {
colors: IColors;
sizes: ISizes;
boxShadows: IBoxShadows;
zIndexes: IZIndexes;
borderRadius: IBorderRadius;
transitions: ITransitions;
}
export const Theme: ITheme = {
colors,
sizes,
boxShadows,
zIndexes,
borderRadius,
transitions,
};
และฉันกำลังใช้ <ThemeProvider> จาก import { ThemeProvider } from 'styled-components';
<ThemeProvider theme={Theme}>
ฉันใช้เวอร์ชันที่เกือบจะเหมือนกับของคุณ:
"styled-components": "^5.3.3",
"@types/styled-components": "^5.1.19",
และนี่คือ tsconfig.json ของฉัน
{
"compilerOptions": {
"jsx": "react-jsx",
"target": "es5",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noFallthroughCasesInSwitch": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"baseUrl": "src",
"paths": {
"~/*": ["./*"]
}
},
"include": [
"src"
]
}
คำตอบ #2
ในไทป์สคริปต์ การกำหนดประเภทมีความสำคัญมาก
1. ธีม
import {ThemeProvider} from 'styled-components';
<ThemeProvider theme={theme}>
//Your children component here
</ThemeProvider>
สำหรับประเภท
//./styled-components.d.ts
import themeVariables from '<//theme variables path here>';
type ThemeInterface = typeof themeVariables
declare module "styled-components" {
interface DefaultTheme extends ThemeInterface {}
}
//tsconfig.json
{
"compilerOptions": {
"includes": ["styled-components.d.ts"]
}
}
หลังจากนั้น คุณสามารถใช้ธีมในคอมโพเนนต์ที่มีการจัดสไตล์ได้
const SomeStyledComponent = styled.div`
background-color: ${props => props.theme.backgroundColor};
`
2.<{ invertedColor: boolean }> ปัญหา
interface SomeComponentProps {
invertedColor: boolean;
}
const SomeComponent = styled.div<SomeComponentProps>`
color: ${props => (props.invertedColor ? props.theme.color.white : props.theme.color.dark)}
`
