打字稿-是否可以定义混合对象的类型而无需分别检查每个属性?

时间:2018-12-19 17:47:24

标签: typescript

我有一个阵列颜色。对于必须的颜色,我只存储一个值,但是对于灰色,我存储从白色到黑色的颜色数组。

export const COLORS = {
   GREEN_BACKGROUND: "#00d8ae",
   GREEN_TEXT: "#038c72",
   BLUE: "#162044",
   GRAYS: Array.from(Array(15).keys()).map(
      (_, i) => {
         const brightness = 16 * (1 + i)
         return `rgb(${brightness}, ${brightness}, ${brightness})`
       },
   ),
}

我正在寻找定义此类对象类型的简写。如果没有Grays数组,我们可以这样做:

interface IColors = {
    [k:string] : string
}

但是尝试

interface IColors {
    [k:string] : string
    Grays: string[]   
}

产生错误,因为Grays对象不遵循上一行中设置的规则。

当前是否有一种无需单独定义每个属性的类型即可编写此类的方法? 我们当然可以使用联合类型

interface IColors {
    [k:string] : string | string[]
}

但是,这将扩大单个颜色的类型,并阻止我们将示例的COLOR.blue作为字符串传递。

1 个答案:

答案 0 :(得分:1)

我确定这个问题已经在其他地方回答了,但是我的搜索能力还不够。当前没有适合您的完美解决方案。以下是进行操作的可能方法:

  • 具有联合类型的索引签名很简单并且是类型安全的,但是正如您所指出的,它比您要描述的类型还要宽。

  • 您可以像这样使用intersection类型:

    \documentclass{article}
    \usepackage{array}
    \newcolumntype{L}{>{\centering\arraybackslash}m{3cm}}
    
    \begin{document}
    
    \begin{table}
        \begin{tabular}{|c|L|L|}
            \hline
            Title 1 & Title 2 & Title 3 \\
            \hline 
            one-liner & multi-line and centered & \multicolumn{1}{m{3cm}|}{multi-line piece of text to show case a multi-line and justified cell}   \\
            \hline
            apple & orange & banana \\
            \hline
            apple & orange & banana \\
            \hline
        \end{tabular}
    \end{table}
    \end{document}
    

    当您从type IColors = {[k: string]: string} & {GRAYS: string[]}; declare const COLORS: IColors; const str = COLORS.PURPLE; // string const arr = COLORS.GRAYS; // string[] 中读取内容时,此方法将为您工作,而在您写入时则无效。此交叉点类型相对简单,但不是类型安全的。具体来说,您上面的代码会给您一个错误:

    COLORS

    ,您必须使用// Property 'GRAYS' is incompatible with index signature. const COLORS: IColors = { ... } 之类的方法来解决它:

    Object.assign()
  • 您可以放弃索引签名,而使用genericconditional类型来表示“一堆// okay const COLORS: IColors = Object.assign({ GREEN_BACKGROUND: "#00d8ae", GREEN_TEXT: "#038c72", BLUE: "#162044" }, { GRAYS: Array.from(Array(15).keys()).map( (_, i) => { const brightness = 16 * (1 + i) return `rgb(${brightness}, ${brightness}, ${brightness})` }, ), }); 属性的确切概念,除非键是{ {1}},在这种情况下,它是一个string属性” ...以及一个辅助函数来推断常量"GRAYS"的通用类型:

    string[]

    可以说这大部分是正确的并且可以安全输入,但实际上并不简单。接受这种类型的任何函数都必须是通用的,以便它可以推断键。

  • 您可以完全放弃此混合类型,而转向TypeScript的意愿,而不是相反。您最终可能会更快乐:

    COLORS

    是的,它的结构不同,但是足够简单,键入安全且易于使用。

您想使用其中哪一种(如果有)取决于您和您的用例。希望能有所帮助;祝你好运!