简体   繁体   English

无法声明多个自定义命名属性 TypeScript MUI v5 Palette

[英]Unable to declare multiple custom named properties TypeScript MUI v5 Palette

I am trying to setup many custom attributes to keep things semantically easy to update in the future.我正在尝试设置许多自定义属性,以使将来在语义上易于更新。 However I am having issues with having more than just one custom property in MUI v5但是,我在 MUI v5 中拥有多个自定义属性时遇到了问题

Ts Error Ts 误差

TS2717: Subsequent property declarations must have the same type. Property 'background' must be of type 'TypeBackground', but here has type 'PaletteColor'.

palette.ts调色板.ts

export const palette = {
  primary: {
    light: '#6D6B8C',
    main: '#6514DD',
    dark: '#6D6B8C',
  },
  secondary: {
    main: '#6D6B8C',
  },
  error: {
    main: '#bd4646',
  },
  background: {
    main: '#fff',
    paper: '#F5F5F5',
  },
  border: {
    main: '#DADAE1',
    primary: '#DADAE1',
  },
  text: {
    primary: '#6D6B8C',
    secondary: '#000',
  },
}


declare module '@mui/material/styles' {
  interface Palette {
    border: Palette['primary']
    background: Palette['primary']
  }

  // allow configuration using `createTheme`
  interface PaletteOptions {
    border?: PaletteOptions['primary']
    background?: PaletteOptions['primary']
  }
}

在此处输入图像描述

You're using a feature of TypeScript called declaration merging .您正在使用 TypeScript 的一项功能,称为声明合并 The problem is because non-function members of the interfaces should be unique.问题是因为接口的非函数成员应该是唯一的。 If they are not unique, they must be of the same type (see docs here ).如果它们不是唯一的,则它们必须属于同一类型(请参阅此处的文档)。

A quick aside: Using declare module 'foo' to import and merge existing objects is called module augmentation , which is a special type of declaration merging.顺便说一句:使用declare module 'foo'来导入和合并现有对象称为模块扩充,这是一种特殊类型的声明合并。 You can actually merge two interfaces with the same name in the same file.您实际上可以在同一个文件中合并两个具有相同名称的接口。


A Possible Solution一个可能的解决方案

Since it's not possible to merge two members of different types with declaration merging, an alternative could be to simply declare a new type.由于无法通过声明合并来合并两个不同类型的成员,因此一种替代方法可能是简单地声明一个新类型。

/// animal.ts
export interface Animal {
  name: string
  age: number
  birthday: string // goal: represent birthday as a `Date` instead of `string`
}


/// pet.ts
import { Animal } from './animal'

// remove the offending property from `Animal`, while simultaneously
// extending the new `Pet` type to add `birthday` back in as a `Date`
type Pet = Omit<Animal, 'birthday'> & {
  birthday: Date
  ownerId: number
}

// the compiler accepts the augmented definition of `Pet`
const pet: Pet = {
  name: 'fido',
  age: 2,
  birthday: new Date(), // see, not a string!
  ownerId: 1
}

Explanation解释

Since declare module adds extra noise, I'll leave it out to make the example more intuitive.由于declare module增加了额外的噪音,我将省略它以使示例更直观。 Consider the following code snippet:考虑以下代码片段:

/// animal.ts - good
export interface Animal {
  name: string
  age: number
}

export interface Animal {
  birthday: string
}

The above code is completely allowed in TypeScript.上述代码在 TypeScript 中是完全允许的。 The compiler merges the two separate declarations of Animal into a single definition.编译器将Animal的两个单独声明合并到一个定义中。

Let's look at a different example.让我们看一个不同的例子。

/// animal.ts - bad
export interface Animal {
  name: string
  age: number
  birthday: string
}

export interface Animal {
  birthday: Date
}

Hopefully, the problem is obvious.希望问题很明显。 Both declarations of Animal have birthday , but of different types. Animal的两个声明都有birthday ,但类型不同。 How is the compiler supposed to know what type birthday should be?编译器应该如何知道birthday应该是什么类型? It could make some assumptions, but thankfully it does't, instead preferring to give an error:它可以做出一些假设,但幸运的是它没有,而是宁愿给出一个错误:

typescript: Subsequent property declarations must have the same type. Property 'birthday' must be of type 'string', but here has type 'Date'.

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM