我正在使用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' | ...
等?
答案 0 :(得分:3)
定义对象时可以使用辅助函数。该函数将具有一个类型参数,该参数要求所有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
你也可以输入它来返回Record
,但我不认为这会增加任何值
function createStyleMap<T extends { [name: string]: CSSProperties }>(cfg: T) : Record<keyof T, CSSProperties> {
return cfg;
}
答案 1 :(得分:1)
在学习了更多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);