打字稿 – 我想在TS中完全不可变对象

我有一些大的对象,比如

const a={
 b:33, 
 c:[78, 99], 
 d:{e:{f:{g:true, h:{boom:'selecta'}}}};/// well, even deeper than this...

而且我希望TS不要允许我这样做

a.d.e.f.h.boom='respek';

我怎样才能完全固定物体?是仅通过为每个深层嵌套对象创建“readonly”接口和接口?

最佳答案 如 https://www.typescriptlang.org/docs/handbook/interfaces.html中所述,您可以在类/接口属性上使用只读或Readonly< …> / ReadonlyArray<>用于不可变对象和数组.在您的情况下,这将如下所示:

const a: Readonly<{
    b: number,
    c: ReadonlyArray<number>,
    d: Readonly<{
        e: Readonly<{
            f: Readonly<{
                g: boolean,
                h: Readonly<{
                    boom: string
                }>
            }>
        }>
    }>
}> = {
        b: 33,
        c: [78, 99],
        d:{e:{f:{g:true, h:{boom:'selecta'}}}}
}

a.d.e.f.h.boom = 'respek'; // error: Cannot assign to 'boom' because it is a constant or a read-only property.

显然,这是相当重言的声明,所以我建议你为你的对象定义合适的类结构.只是声明一个嵌套的无类型对象,你并没有真正利用任何Typescript的功能.

但是,如果你真的需要没有类型定义,我认为唯一的方法是定义一个冰箱(喜欢这个术语:D),就像Hampus建议的那样.取自deepFreeze(obj)函数from MDN:

function freezer(obj) {
    Object.getOwnPropertyNames(obj).forEach(name => {
        if (typeof obj[name] == 'object' && obj[name] !== null)
            freezer(obj[name]);
    });
    return Object.freeze(obj);
}

const a = freezer({
    b:33, 
    c:[78, 99], 
    d:{e:{f:{g:true, h:{boom:'selecta'}}}}});

a.d.e.f.h.boom='respek'; // this does NOT throw an error. it simply does not override the value.

tl; dr:如果没有定义类型,则无法获得编译器类型错误.这就是打字稿的重点.

编辑:

这最后的陈述是错误的.例如,

let a = 1
a = "hello"

将抛出错误,因为类型隐式设置为数字.但是,对于readonly,我认为,您将需要上面定义的适当声明.

点赞