typescript - 如何创建元组的并集?

标签 typescript

我正在开发一个纯终端库,它正在用 TypeScript 重写 jQuery Terminal。

我有这个代码:

type Effect = 'g' | 'b' | 'i' | 'u' | 's' | 'o';
type NotEffect = `-${Effect}`;
type Item = '!' | '@';
type Effects = Array<Effect | NotEffect | Item>;
type Stack = Array<string>;

type Style = {[key: string]: string};
type Attrs = {[key: string]: string} & {style?: Style};

type Formating = [
    Effects,
    string,
    string,
    Array<string> | undefined,
    string | undefined,
    Attrs | undefined
];

const output: Formating = [[], '', '', undefined, undefined, undefined];

在格式中添加 undefined 是解决具有不同长度元素的联合类型问题的解决方法,这导致了该问题:

type Formating = [Effects, string, string]
  | [Effects, string, string, Array<string>]
  | [Effects, string, string, Array<string>, string]
  | [Effects, string, string, Array<string>, string, Attrs]

当我想设置格式的第四个和下一个元素时,添加此类型会出错。添加 undefined 解决了 TypeScript 的问题,但它改变了 JavaScript 代码的行为。我需要添加一些技巧来解决格式具有未定义值的问题。

有没有办法用可变数量的元素格式化元组?

编辑

这是我的真实代码:

const class_i = 3; // index of the class in formatting
const attrs_i = 5; // index of attributes in formattings

function get_inherit_style(stack: Stack) {
    const output: Formating = [[], '', ''];
    function update_attrs(value: string) {
        if (!output[attrs_i]) {
            output[attrs_i] = {};
        }
        try {
            const new_attrs = JSON.parse(value);
            if (new_attrs.style) {
                const new_style = new_attrs.style;
                const old_style = output[attrs_i].style;
                output[attrs_i] = {
                    ...new_attrs,
                    ...output[attrs_i],
                    ...{
                        style: update_style(new_style, old_style)
                    }
                };
            } else {
                output[attrs_i] = {
                    ...new_attrs,
                    ...output[attrs_i]
                };
            }
        } catch (e) {
            warn('Invalid JSON ' + value);
        }
    }

    if (!stack.length) {
        return output;
    }
    for (let i = stack.length; i--;) {
        let formatting = parse_formatting(stack[i]);
        if (formatting.length > 5) {
            const last = formatting.slice(5).join(';');
            formatting = formatting.slice(0, 5).concat(last);
        }
        const style = formatting[0].split(/(-?[@!gbiuso])/g).filter(Boolean);
        style.forEach(function(s) {
            if (is_valid_effect(s) && output[0].indexOf(s) === -1) {
                output[0].push(s);
            }
        });
        for (let j = 1; j < formatting.length; ++j) {
            const value = formatting[j].trim();
            if (value) {
                if (j === class_i) {
                    if (!output[class_i]) {
                        output[class_i] = [];
                    }
                    const classes = value.split(/\s+/);
                    output[class_i] = output[class_i].concat(classes);
                } else if (j === attrs_i) {
                    update_attrs(value);
                } else if (!output[j]) {
                    output[j] = value;
                }
            }
        }
    }
    return stringify_formatting(output);
}

我遇到一个错误:

Tuple type '[Effects, string, string]' of length '3' has no element at index '3'

访问输出[class_i]

最佳答案

TypeScript 支持optional elements in tuple types如果使用未标记的元组元素,则通过将 ? 添加到类型的末尾来编写:

type Formatting = 
 [Effects, string, string, Array<string>?, string?, Attrs?];

或者如果使用 labeled tuple elements 则到标签末尾:

type Formatting = 
  [a: Effects, b: string, c: string, d?: Array<string>, e?: string, f?: Attrs];

无论哪种方式都会产生允许相应元素存在或缺失的效果:

const output: Formatting = [[], '', '']; // okay
const output2: Formatting = [[], '', '', ["a"], "abc"]; // okay

Playground link to code

关于typescript - 如何创建元组的并集?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76863045/

相关文章:

javascript - gulp-concat 文件中的 typescript

TypeScript:在具有类型安全性的运行时向类添加动态字段

javascript - 应用状态接口(interface)中的 NgRx 根状态键

typescript - 如何使用 TypeScript 对使用 Vue 的 .js 文件进行类型检查?

javascript - 扩展 Joi 未实现自定义运算符

typescript - 类型 '{ useNewUrlParser: boolean; useUnifiedTopology: boolean}' 的参数不可分配给类型的参数'

reactjs - 如何在 Typescript 中为 React useReducer Hook 操作创建类型定义?

typescript - 如何将语法 "inputs"属性更改为 "@Input"属性装饰器

javascript - 将 HTML 字符串(包括样式)转换为 PDF(Electron - React - Typescript)

javascript - 在 TypeScript 中生成整数数组