我正在使用JSS并且想要使用强类型键和值来定义style
对象,而不是两次定义键。
第一次尝试:
const style: Record<string, CSSProperties> = {
root: {
background: 'red'
},
title: {
fontWeight: 'bold'
},
...
}
现在style
没有强类型,因此编译器在访问style.nonExistingKey
时不会发出警告。
第二次尝试:
如果我明确指定键如下:
const style: Record<'root' | 'title' | ... , CSSProperties> = {
root: {
background: 'red'
},
...
}
然后我得到一个强类型的记录,即style.nonExistingKey
将抛出一个错误。但是,此方法需要复制记录键,因为它们必须显式添加为通用参数。
第三次尝试:
我可以使用以下代码在事后创建强类型记录:
const styleObj = {
root: {
background: 'red'
},
title: {
fontWeight: 'bold'
},
...
}
const style = styleObj as Record<keyof typeof styleObj, CSSProperties>
但是,我丢失了记录的CSSProperties
值的类型检查,所以这不是一个好的解决方案。
有没有办法做这样的事情:
const style: Record<T, CssProperties> = {
root: {
background: 'red'
},
...
}
并将T
自动推断为'root' | 'title' | ...
等?
定义对象时可以使用辅助函数。该函数将具有一个类型参数,该参数要求所有proepries必须使用索引签名为CSSProperies
类型。由于函数是通用的,结果将被正确输入(它实际上不会有索引签名,而只是定义的proepries)
function createStyleMap<T extends { [name: string]: CSSProperties }>(cfg: T) {
return cfg;
}
const style = createStyleMap({
root: {
background: 'red'
},
title: {
fontWeight: 'bold'
}
});
style.root //ok
style['hu'] // error
你也可以输入returnRecord
,但我认为这不会增加任何价值
function createStyleMap<T extends { [name: string]: CSSProperties }>(cfg: T) : Record<keyof T, CSSProperties> {
return cfg;
}
在学习了更多TypeScript之后,我设法让它在一个函数中运行。所以这里有新的,简短的工作解决方案。
import { StyleRulesCallback, Theme } from 'material-ui/styles';
import { CSSProperties } from 'react';
export const createStyleMap =
<T extends keyof any>(callback: (theme: Theme) => Record<T, CSSProperties>):
StyleRulesCallback<T extends string ? T : never> => callback;
import { withStyles, WithStyles } from 'material-ui/styles';
import React from 'react';
import { createStyleMap } from '../utils/utils';
interface OwnProps {
dummyName: string;
}
const styles = createStyleMap(theme =>
({
content: {
height: '100%',
padding: theme.spacing.unit * 3,
overflowY: 'auto',
boxSizing: 'border-box'
},
tableHead: {
height: 56
}
})
);
type Props = OwnProps
& WithStyles<keyof ReturnType<typeof styles>>;
class DummyComponent extends React.Component<Props> {
render() {
return <div className={this.props.classes.content}/>;
}
}
export default withStyles(styles)(DummyComponent);