![](/img/trans.png)
[英]Using props.children and styled-component "as" prop with typescript
[英]Conditionally set attributes in styled-component using props to index on theme object with TypeScript?
我有一個使用styled-components
ThemeProvider
的next.js
(react) TypeScript 項目。 我正在嘗試對theme
對象進行索引,該對象將基於rem
的字體大小存儲為strings
並按點大小( integer
)進行索引。 我遇到的問題是我無法根據從組件傳遞的 prop 動態設置索引。 錯誤消息、代碼示例、嘗試的解決方案和觀察結果如下
Element implicitly has an 'any' type because expression of type 'number' can't be used to index type '{ 14: string; 12: string; 10: string; }'.
No index signature with a parameter of type 'number' was found on type '{ 14: string; 12: string; 10: string; }'.
樣式.d.ts
import "styled-components";
declare module "styled-components" {
export interface DefaultTheme {
fonts: {
size: {
14: string;
12: string;
10: string;
};
}
}
}
theme
對象主題.ts
import { DefaultTheme } from "styled-components";
const theme: DefaultTheme = {
fonts: {
size: {
14: "0.875rem",
12: "0.75rem",
10: "0.625rem"
},
}
};
export { theme };
組件.ts
import styled from "styled-components";
const StyledThingie = styled('div')`
/*
HERE IS WHERE THIS ISSUE IS
I want to conditionally inject the prop (if fontSize is passed)
into the size index to get the rem-based size, and set a default
font-size if no prop is passed.
props.theme.fonts.size[10] works just fine.
*/
font-size: ${props => (props.fontSize ? props.theme.fonts.size[props.fontSize] : props.theme.fonts.size[10])};
`;
export {
StyledThingie
}
Thingie.tsx
import React from "react";
import styled from "styled-components";
import { StyledThingie } from "./components.ts";
const Thingie = styled(StyledThingie)`
display: block;
`;
const ThingieComponent: React.FC<any> = (props) => {
return(
<Thingie fontSize={14}> // HERE IS WHERE I"M PASSING THE PROP
<p>This paragraph should be set to 0.875rem or theme.fonts.size[14] </p>
</Thingie>
);
}
我試圖根據一些TypeScript 文檔定義index signature
,但不清楚如何實現這一點。 這是我的嘗試:
interface FontSize {
[index: string]: number;
}
export type StyledThingieProps = {
fontSize?: FontSize;
}
const StyledThingie = styled('div')<StyledThingieProps>`
size: ${props => (props.fontSize ? props.theme.fonts.size[props.fontSize] : props.theme.fonts.size[10])};
`;
我的腦袋疼 ... ;)
當您使用變量索引具有非動態屬性的類型時會導致該錯誤。 因此,要繞過它,您需要更改DefaultTheme.fonts.size
的類型聲明以定義動態屬性。 (基本上,類型檢查器無法知道傳遞給索引 ( []
) 的變量是否與聲明的鍵之一完全匹配。因此您必須說“我可以使用任何數字或字符串鍵” .)
如果您仍想聲明已知鍵:
export interface DefaultTheme {
fonts: {
size: {
[key: number]: string;
14: string;
12: string;
10: string;
};
}
但是,如果你不關心具體的字體大小是什么,你可以這樣做
export interface DefaultTheme {
fonts: {
size: {
[key: number]: string;
};
}
這兩個選項修復了類型定義以接受任何數字作為鍵。 或者,您可以將fontSize
強制轉換為鍵類型(使用keyof
),它基本上是一個enum
,其中包含對象的所有鍵作為值。 你告訴類型檢查器“這個變量應該是這些特定值中的任何一個(特定類型中的任何鍵)”:
// in the template where you use the font size
props.theme.fonts.size[props.fontSize as keyof typeof props.theme.fonts.size]
// or using the type declaration directly
props.theme.fonts.size[props.fontSize as keyof DefaultTheme["font"]["size"]]
通過聲明字體大小的類型,您也走上了正確的軌道,但是語法有點錯誤:
export type StyledThingieProps = {
fontSize?: keyof DefaultTheme["font"]["size"];
}
這是修復它的另一種方法。
我通過以下方式解決了它:
export const TextInput = styled.TextInput.attrs(({theme}) => ({ placeholderTextColor: theme.colors.primary, }))
font-family: ${({ theme }) =`enter code here`> theme.fonts.interBold};
font-size: 18px;
color: ${({ theme }) => theme.colors.primary};
;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.