如何从打字稿中的类型中排除

如何从打字稿中的类型中排除

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

问题描述

类中的 Getter 是只读属性,因此从以下代码中抛出类型错误是有意义的.

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.
    }
}

有没有办法将可写属性强制转换为类型并排除所有 getter?

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

游乐场示例

推荐答案

虽然 readonly 不直接影响类型是否可赋值,但会影响它们是否相同.为了测试两种类型是否相同,我们可以滥用(1)条件类型的可分配性规则,它要求 extends 之后的类型相同,或者(2)交叉类型的推理过程,从双方抛出相同的类型.然后我们只使用 Titian Cernicova-Dragomir 的回答中的映射类型依次查看 Car 的每个属性,看看它是否与自身的可变版本相同.

While readonly does not directly affect whether types are assignable, it does affect whether they are identical. To test whether two types are identical, we can abuse either (1) the assignability rule for conditional types, which requires that the types after extends be identical, or (2) the inference process for intersection types, which throws out identical types from both sides. Then we just use mapped types as in Titian Cernicova-Dragomir's answer to look at each property of Car in turn and see whether it is identical to a mutable version of itself.

// https://github.com/Microsoft/TypeScript/issues/27024#issuecomment-421529650
type IfEquals<X, Y, A, B> =
    (<T>() => T extends X ? 1 : 2) extends
    (<T>() => T extends Y ? 1 : 2) ? A : B;

// Alternatively:
/*
type IfEquals<X, Y, A, B> =
    [2] & [0, 1, X] extends [2] & [0, 1, Y] & [0, infer W, unknown]
    ? W extends 1 ? B : A
    : B;
*/

type WritableKeysOf<T> = {
    [P in keyof T]: IfEquals<{ [Q in P]: T[P] }, { -readonly [Q in P]: T[P] }, P, never>
}[keyof T];
type WritablePart<T> = Pick<T, WritableKeysOf<T>>;

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

function applySnapshot(
    car: Car,
    snapshoot: Partial<WritablePart<Car>>
) {
    let key: keyof typeof snapshoot;
    for (key in snapshoot) {
        if (!snapshoot.hasOwnProperty(key)) continue;
        car[key] = snapshoot[key];
    }
}

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

08-18 12:16