Javascript 用材料拓展主题-ui@next和打字稿
在为Javascript 用材料拓展主题-ui@next和打字稿,javascript,typescript,material-ui,Javascript,Typescript,Material Ui,在为材质ui创建主题时,我添加了两个新的调色板选项,它们为我提供了更好的明暗范围。我扩展了主题类型来表示这一点 import {Theme} from "material-ui/styles"; import {Palette} from "material-ui/styles/createPalette"; export interface ExtendedTheme extends Theme { palette: ExtendedPalette } export interfa
材质ui
创建主题时,我添加了两个新的调色板选项,它们为我提供了更好的明暗范围。我扩展了主题
类型来表示这一点
import {Theme} from "material-ui/styles";
import {Palette} from "material-ui/styles/createPalette";
export interface ExtendedTheme extends Theme {
palette: ExtendedPalette
}
export interface ExtendedPalette extends Palette {
light: Color,
dark: Color,
}
当我尝试在with styles
渲染帮助器中使用这些附加选项时,就会出现问题
const styles = (theme : ExtendedTheme) => ({ root: {color: theme.light['100'] }});
export interface MyProps {classes: {[index: string] : string}};
const MyComponent = (props : MyProps) => {...};
// Type ExtendedTheme is not assignable to Theme
export default withStyles(styles : StyleRulesCallback)(MyComponent);
从功能上讲,我的代码在纯javascript中运行良好,但由于类型不同,因此会抛出错误。material ui的键入要求样式回调函数的唯一参数为主题类型
:
export type StyleRulesCallback<ClassKey extends string = string> = (theme: Theme) => StyleRules<ClassKey>;
导出类型StyleRulesCallback=(主题:主题)=>StyleRules;
我认为扩展一个接口将以多态的方式工作,这样
ExtendedTheme
将实现Theme
我想到的唯一答案就是让我的自定义选项像这样可选
export interface ExtendedPalette extends Palette {
light?: Color,
dark?: Color,
}
然后在我的样式回调中,我必须检查这些选项是否存在,这有点麻烦,但我认为没有任何其他解决方法
const styles = (theme : ExtendedTheme) => {
let light = theme.palette.light[100];
if(light === undefined) light = theme.common.white;
{ root: {color: light }}
};
这样做的原因是,当我使用with style
时,主题对象被传递给回调,但是这个回调的类型使用主题
类型,因为它们无法知道我的扩展主题
类型。当ExtendedTheme
必须有Theme
不知道的选项时,就会发生冲突。通过使这些额外选项成为可选的主题
仍然可以符合扩展主题
。基本上,扩展接口可以在预期父接口的位置传递,但不能在预期扩展接口的位置传递其父接口,除非扩展接口以父接口仍可遵循的方式进行扩展
一个简单的例子很有启发性
export interface Foo {foo: string};
export interface Bar extends Foo {bar: string}
function getFoo(f : Foo) {console.log(f.foo)}
function getBar(b : Bar) {console.log(b.bar)}
function getFooBar(fb: Bar) {console.log(fb.foo, fb.bar)}
const f : Foo = {foo: 'foo'}
const b : Bar = {foo: 'foo', bar: 'bar'}
getFoo(f) // foo
getFoo(b) // foo
getBar(f) // Error Incompatible Type
getBar(b) // bar
getFooBar(f) // Error Incompatible Type
getFooBar(b) // foo bar
getFoo(b)
之所以有效,是因为Bar
保证至少拥有Foo
所拥有的一切getBar(f)
和getFooBar(f)
都失败,因为编译器看到类型Foo
没有键bar
通过像这样重新定义Bar
export interface Bar extends Foo {bar? : string}
编译器现在知道Foo与Bar
类型的最低限定条件相匹配,但必须检查隐式null。所以这会起作用
getBar(f)
但是编译器会大喊隐式空值,这很好,因为f.bar
是未定义的。所以你必须像这样重新定义你的函数
function getBar(b : Bar) {
let bar = b.bar
if(bar === undefined) bar = b.foo;
console.log(bar);
}
getBar(b) // bar
getBar(f) // foo
可以使用以下方法解决此问题: 此外,您还可以在应用程序组件中声明该模块,并将子模块包装到
ThemeProvider
:
import { createMuiTheme, ThemeProvider, colors, ThemeOptions } from '@material-ui/core';
declare module '@material-ui/core' {
interface Theme {
colors: {
success: {
dark: string,
light: string,
}
}
}
}
const App = () => {
const theme = createMuiTheme({
colors: {
success: {
dark: colors.green[600],
light: colors.green[300],
},
} as ThemeOptions,
});
return (
<ThemeProvider theme={theme}>
<a href="https://material-ui.com/customization/theming/">Theming</a>
</ThemeProvider>
)
从'@material ui/core'导入{createMuiTheme,ThemeProvider,colors,ThemeOptions};
声明模块“@material ui/core”{
界面主题{
颜色:{
成功:{
黑暗:弦,
轻:弦,
}
}
}
}
常量应用=()=>{
const theme=createMuiTheme({
颜色:{
成功:{
深:颜色。绿色[600],
光:颜色。绿色[300],
},
}作为人民,,
});
返回(
)
注意,在声明模块的地方,您应该导入正在扩展的接口。例如,从“@material ui/core/styles/createMuiTheme”导入{Theme}”
import { createMuiTheme, ThemeProvider, colors, ThemeOptions } from '@material-ui/core';
declare module '@material-ui/core' {
interface Theme {
colors: {
success: {
dark: string,
light: string,
}
}
}
}
const App = () => {
const theme = createMuiTheme({
colors: {
success: {
dark: colors.green[600],
light: colors.green[300],
},
} as ThemeOptions,
});
return (
<ThemeProvider theme={theme}>
<a href="https://material-ui.com/customization/theming/">Theming</a>
</ThemeProvider>
)