TypeScript:使用类型转换进行类型保护

问题描述 投票:0回答:2

我有一个带有构造函数的类,可以接受两种类型的对象,然后根据它得到的对象类型,执行不同的操作。

我已经看到可以使用

as
关键字来实现这一点。 但我感觉不对。

export class Angle {
    #degrees: number;

    constructor(degOrRad: number, radians = false) {
        if (!radians) {
            this.deg = degOrRad;
        } else {
            this.deg = this.#radiansToDegrees(degOrRad);
        }
    }

    #degreesToRadians(degrees: number) {
        return (degrees * Math.PI) / 180;
    }

    #radiansToDegrees(radians: number) {
        return (radians * 180) / Math.PI;
    }
    #getNormalizedDegrees(degrees: number) {
        return degrees % 360
    }
    #getNormalizedRadians(radians: number) {
        return radians % (2 * Math.PI)
    }
    get deg() {
        return this.#degrees
    }
    get rad() {
        return this.#degreesToRadians(this.deg)
    }
    set deg(deg) {
        this.#degrees = deg
    }

    get degNormalized() {
        return  this.#getNormalizedDegrees(this.deg)
    }
    get radNormalized() {
        return this.#getNormalizedRadians(this.rad)
    }

    normalize() {
        const newDeg = this.#getNormalizedDegrees(this.deg)
        return new Angle(newDeg)
    }
    add(angle: Angle): Angle {
        const newDeg = this.deg + angle.deg
        return new Angle(newDeg)
    }
    subtract(angle: Angle): Angle {
        const newDeg = this.deg - angle.deg
        return new Angle(newDeg)
    }
    multiply(angle: Angle): Angle {
        const newDeg = this.deg * angle.deg
        return new Angle(newDeg)
    }

    get sin() {
        return Math.sin(this.rad)
    }
    get cos() {
        return Math.cos(this.rad)
    }
    get tan() {
        return Math.tan(this.rad)
    }
    get ctg() {
        return 1 / Math.tan(this.rad);
    }

    equals(angle: Angle) {
        return this.deg === angle.deg
    }
}
export type VectorAngleInit = {
    angle: Angle,
    magnitude: number
}
export type VectorDInit = {
    dx: number,
    dy: number
}
export class Vector {
    #dx: number;
    #dy: number;
    constructor(init: VectorAngleInit | VectorDInit) {
        if ((init as VectorAngleInit)?.angle) {
            const angleInit = init as VectorAngleInit
            this.#dx = angleInit.magnitude * angleInit.angle.cos;
            this.#dy = angleInit.magnitude * angleInit.angle.sin;
        } else {
            const dInit = init as VectorDInit
            this.#dx = dInit.dx
            this.#dy = dInit.dy
        }
    }
}

我应该用另一种方式吗?如果是这样,您认为哪种方式更好?

javascript typescript class casting typeguards
2个回答
0
投票

这没问题,或者你可以用不同的语法强制它:

if (<VectorAngleInit>init?.angle) {

如果您正在寻找更“合适”的类型检查,

typeof
instanceof
将是您的工具。

if (init instanceof VectorAngleInit && init?.angle) {
// or
if (typeof init === "VectorAngleInit" && init?.angle) {

文档:


0
投票

您可以使用

in
运算符缩小 来检查
"angle"
中是否存在
init
,并将
init
缩小到所需的 联合成员,而不需要 类型断言(您所调用的内容) “铸造”):

export class Vector {
  #dx: number;
  #dy: number;
  constructor(init: Vectorinit | VectorDInit) {
    if ("angle" in init) {
      this.#dx = init.magnitude * init.angle.cos;
      this.#dy = init.magnitude * init.angle.sin;
    } else {
      this.#dx = init.dx
      this.#dy = init.dy
    }
  }
}

Playground 代码链接

© www.soinside.com 2019 - 2024. All rights reserved.