我们可以检查属性是否为只读

Dak*_*ito 0 typescript

我尝试使用 getOwnPropertyDescriptor 方法,但作为回报,普通属性或只读属性总是可写?你知道有什么方法可以检查吗?

Nan*_*gin 7

readonly打字稿有两种,编译时只读和运行时只读。

由于OP中没有提供代码,我想,根据问题,代码如下:

class Foo {
    readonly a = 1
    b = 2
}
Run Code Online (Sandbox Code Playgroud)

我们还可以定义一个辅助函数来检查readonly给定对象的属性的-ness

function isWritable<T extends Object>(obj: T, key: keyof T) {
    const desc = Object.getOwnPropertyDescriptor(obj, key) || {}
    return Boolean(desc.writable)
}
Run Code Online (Sandbox Code Playgroud)

然后我们可以检查readonly-ness:

const foo = new Foo
console.log(isWritable(foo, 'a'), isWritable(foo, 'b'))
// true true
Run Code Online (Sandbox Code Playgroud)

它正在打印,true true因为foo.a并且foo.b在运行时都是可写的,因为readonly打字稿中的关键字对发出的 javascript 代码没有任何作用。

如果我们检查Foo(针对 ES6)发出的代码:

class Foo {
    constructor() {
        this.a = 1;
        this.b = 2;
    }
}
Run Code Online (Sandbox Code Playgroud)

a和根本没有区别b

但是,如果您foo.a在打字稿中为其分配新值,则类型系统会抱怨这a是一个只读属性。这正是readonly关键字的作用:它只提供编译时间约束,永远不会影响运行时行为。

class Foo {
    constructor() {
        this.a = 1;
        this.b = 2;
    }
}
Run Code Online (Sandbox Code Playgroud)

如果需要运行时只读属性,则get可以使用语法。

foo.a = 1 // Cannot assign to 'a' because it is a constant or a read-only property.
foo.b = 3 // correct
Run Code Online (Sandbox Code Playgroud)

发出的代码将是:

class Zoo {
    constructor() {
        this.b = 2;
    }
    get a() { return 1; }
}
Run Code Online (Sandbox Code Playgroud)

由于 getter 存在于原型上而不是实例上,我们需要isWritable稍微修改函数以覆盖getter.

function isWritable<T extends Object>(obj: T, key: keyof T) {
    const desc = 
        Object.getOwnPropertyDescriptor(obj, key) 
        || Object.getOwnPropertyDescriptor(Object.getPrototypeOf(obj), key)
        || {}
    return Boolean(desc.writable)
}
Run Code Online (Sandbox Code Playgroud)

然后我们readonly再次检查-ness:

class Zoo {
    get a () { return 1 }
    b = 2
}

Run Code Online (Sandbox Code Playgroud)

现在zoo.a在编译时和运行时都是只读的。

class Zoo {
    constructor() {
        this.b = 2;
    }
    get a() { return 1; }
}
Run Code Online (Sandbox Code Playgroud)

在线试用

警告

修改后isWritable的仍然不完善,因为它只检查原型链上的一个级别。一个完整的解决方案应该爬上原型链,直到找到一个描述符或到达终点。