首页 > 解决方案 > TypeScript 中的条件嵌套数组元素

问题描述

这是简化控制台输出格式的函数:

function generateConsoleMethodParametersForFormattedOutput(
    formattedOutputData: Array<[string, { [CSS_Key: string]: string; }]>
): Array<string> {

    const outputContents: Array<string> = [];
    const CSS_DeclarationsForEachContent: Array<string> = [];

    for (const singleFormattedOutputData of formattedOutputData) {

        outputContents.push(`%c${singleFormattedOutputData[0]}`);

        let CSS_Declarations: string = "";

        for (const [ CSS_Key, CSS_Value ] of Object.entries(singleFormattedOutputData[1])) {
        CSS_Declarations = `${CSS_Declarations}${CSS_Key}: ${CSS_Value};`;
        }

        CSS_DeclarationsForEachContent.push(CSS_Declarations);
    }

    return [ outputContents.join(""), ...CSS_DeclarationsForEachContent ];
}

现在我们可以将格式化输出为:

console.log(...generateConsoleMethodParametersForFormattedOutput([
    [ " Red bold ", { background: "red", color: "white", "font-weight": "bold", "border-radius": "4px" } ],
    [ " Blue italic", { color: "blue", "font-style": "italic" } ]
]));

如果我们想在 中添加条件元素generateConsoleMethodParametersForFormattedOutput([])怎么办?基本方法是:

[  "RequiredElement", condition ? [ "ConditionlaElement" ] : [] ]

在这里,我们遇到了 TypeScript 错误:

console.log(...generateConsoleMethodParametersForFormattedOutput([
    [ " Red bold ", { background: "red", color: "white", "font-weight": "bold", "border-radius": "4px" } ],
    [ " Blue italic", { color: "blue", "font-style": "italic" } ],
    ...mockCondition ? [ [ " Teal ", { color: "teal" } ] ] : []
]));
Type '(string | { color: string; })[]' is not assignable to type '[string, { [CSS_Key: string]: string; }]'.
  Target requires 2 element(s) but source may have fewer.(2322)

但是编译后的 JavaScript 可以工作:

在此处输入图像描述

我的错误还是 TypeScript 错误?

小提琴

标签: typescript

解决方案


问题

在表达式...mockCondition ? [ [ " Teal ", { color: "teal" } ] ] : []中,为三元条件的结果推断出的类型将是(string | { color: string; })[](一个通用的无限数组)而不是[string, { [CSS_Key: string]: string; }](元组类型)。这是因为表达式不是在编译时计算的,所以它的结果类型可以/不与函数参数的类型“匹配”。

解决方案

使用类型断言。

type OutputData = Array<[string, { [CSS_Key: string]: string; }]>
// ^^^^^ declare type here

function generateConsoleMethodParametersForFormattedOutput(
    formattedOutputData: OutputData
): Array<string> {

    const outputContents: Array<string> = [];
    const CSS_DeclarationsForEachContent: Array<string> = [];

    for (const singleFormattedOutputData of formattedOutputData) {

        outputContents.push(`%c${singleFormattedOutputData[0]}`);

        let CSS_Declarations: string = "";

        for (const [ CSS_Key, CSS_Value ] of Object.entries(singleFormattedOutputData[1])) {
        CSS_Declarations = `${CSS_Declarations}${CSS_Key}: ${CSS_Value};`;
        }

        CSS_DeclarationsForEachContent.push(CSS_Declarations);
    }

    return [ outputContents.join(""), ...CSS_DeclarationsForEachContent ];
}


declare const mockCondition: boolean


console.log(...generateConsoleMethodParametersForFormattedOutput([
    [ " Red bold ", { background: "red", color: "white", "font-weight": "bold", "border-radius": "4px" } ],
    [ " Blue italic", { color: "blue", "font-style": "italic" } ],
    ...(mockCondition ? [ [ " Teal ", { color: "teal" } ] ] : []) as OutputData // type asssertion
]));

操场


推荐阅读