如何从打字稿中的类型中排除仅吸气剂的属性 [英] How to exclude getter only properties from type in typescript

查看:102
本文介绍了如何从打字稿中的类型中排除仅吸气剂的属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

类中的字母是只读属性,因此以下代码引发类型错误是有意义的.

Getters in the class are readonly properties so throwing type error from following code make sense.

class Car {
    engine: number;
    get hp() {
        return this.engine / 2;
    }
    get kw() {
        return this.engine * 2;
    }
}

function applySnapshot(
    car: Car,
    snapshoot: Partial<Car> // <-- how to exclude readonly properties?
) {
    for (const key in snapshoot) {
        if (!snapshoot.hasOwnProperty(key)) continue;
        car[key as keyof Car] = snapshoot[key as keyof Car];
        // Cannot assign to 'hp' because it is a constant or a read-only property.
    }
}

有没有一种方法可以强制转换仅可写属性以键入和排除所有吸气剂?

Is there a way how to cast writable only properties to type and exclude all getters?

推荐答案

编辑 有关此问题的解决方法,请参见@ matt-mccutchen.

Edit See @matt-mccutchen for an intresting workaround to this issue.

原始答案

readonly是一个相当弱的修饰符,因为它不会影响可分配性.因此,例如,您可以将具有readonly属性的对象分配给具有相同可变属性的对象,并且编译器不会抱怨:

readonly is a rather weak modifier in that is does not impact assignability. So for example you can assign an object with readonly properties to one with those same mutable properties and the compiler will not complain:

let roCar: Partial<Car> = { hp: 10 } // we can assign a  mutable object to a referecne with a readonly property
roCar.hp = 10; // error hp is readonly

//But we can also assign an object with a readonly property to a fully mutable version of it 
let allMutableCar: { -readonly [P in keyof Car]: Car[P] } = new Car();
allMutableCar.hp = 10; // No compile time error

这是一个已知问题,在此处中记录.

This is a known issue, documented here.

由于此可分配性规则,无法在条件类型中区分只读字段和可变字段之间的差异.

Because of this assignability rule there is no way to distinguish in conditional types the difference between a readonly field and a mutable one.

一种解决方法是在只读字段类型中添加一些额外的内容.这不会影响您如何使用该字段,但会为我们提供一个删除密钥的钩子.

One workaround is to add something extra to the type of readonly fields. This will not impact how you can use the field but it will give us a hook to remove the key.

type readonly = { readonly?: undefined };
class Car {
    engine!: number;
    get hp() : number & readonly {
        return this.engine / 2;
    }
    get kw() : number & readonly {
        return this.engine * 2;
    }
}

type NoReadonlyKeys<T> = { [P in keyof T]: 'readonly' extends keyof T[P] ? never : P }[keyof T]

type PartialNoReadonly<T> = Partial<Pick<T, NoReadonlyKeys<T>>>  
type Mutable<T> = { -readonly [P in keyof T]: T[P] }
function applySnapshot(
    car: Car,
    snapshoot: PartialNoReadonly<Car>
) {
    const mutableCar: Mutable<Car> = car; // erase readonly so we can mutate
    for (const key in snapshoot) {
        let typedKey = key as keyof typeof snapshoot
        if (!snapshoot.hasOwnProperty(key)) continue;
        mutableCar[typedKey] = snapshoot[typedKey] as any;
    }
}

applySnapshot(new Car(), {
    engine: 0
})
applySnapshot(new Car(), {
    hp: 0 /// error
})

这篇关于如何从打字稿中的类型中排除仅吸气剂的属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆