[英]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.