简体   繁体   English

Typescript 铸造总是返回“对象”

[英]Typescript casting always returns “object”

Lets say I have two interfaces which have two the same members id, and name:假设我有两个接口,它们有两个相同的成员 id 和名称:

export interface InterfaceA {
    id: number;
    name: string;
    //some other members
}

export interface InterfaceB {
    id: number;
    name: string;
    //some other members
}

I would like to get collection of elements of both types to populate some combobox.我想收集这两种类型的元素来填充一些 combobox。 I need id, name and type of every element, so I've made following class我需要每个元素的 id、名称和类型,所以我做了以下 class

export class AssignableDevice {
    id: number;
    name: string;
    type: string;

    constructor(device: InterfaceA | InterfaceB) {
        this.id = device.id;
        this.name = device.name;
        this.type = typeof device; //still returns "object"
    }
}

// in onInit method : 

ngOnInit() {
    super.ngOnInit();

    this.dataService.getInterfaceA().subscribe((data) => {
      data.forEach((element) => this.devices.push(new AssignableDevice(element as InterfaceA)));
    });

    this.dataService.getInterfaceB().subscribe((data) => {
      data.forEach((element) => this.devices.push(new AssignableDevice(element as InterfaceB)));
    })
}

But problem is I always get "object" in "AssignableDevice" class constructor, and I have no idea why is this happening.但问题是我总是在“AssignableDevice”class 构造函数中得到“对象”,我不知道为什么会这样。 I can achieve my goal by using some enum, but I wonder, why this solution is not working, and how could achieve this.我可以通过使用一些枚举来实现我的目标,但我想知道为什么这个解决方案不起作用,以及如何实现这一点。 I'd rather not make any changes in InterfaceA or InterfaceB.我宁愿不对 InterfaceA 或 InterfaceB 进行任何更改。

You can't access the TypeScript type of an object at runtime (in the general case).您无法在运行时访问 TypeScript 类型的 object(在一般情况下)。 TypeScript provides a compile-time type system. TypeScript 提供了一个编译时类型系统。 The typeof that you're using is the JavaScript runtime typeof , which always returns "object" for objects of any kind (and for null ).您正在使用的typeof是 JavaScript运行时typeof ,它始终为任何类型的对象(以及null )返回"object"

You've said you want to send the type to the backend, so you definitely need it at runtime.您已经说过要将类型发送到后端,因此在运行时肯定需要它。 I can see at least two ways to do that:我至少可以看到两种方法:

  1. You could define your interfaces as branded interfaces to ensure that you always include the type:您可以将接口定义为品牌接口,以确保始终包含以下类型:

     export interface InterfaceA { id: number; name: string; //some other members type: "InterfaceA"; // <== This is a _string literal type_ whose only valid value is the string "InterfaceA" } export interface InterfaceB { id: number; name: string; //some other members type: "InterfaceB"; // <=== String literal type }

    Now any object you assign to a variable, property, or parameter of type InterfaceA has to have a type property with the string "InterfaceA" and similar for InterfaceB .现在,您分配给InterfaceA类型的变量、属性或参数的任何 object 都必须具有带有字符串"InterfaceA"type属性,并且对于InterfaceB类似。 Then your code would use that type property.然后您的代码将使用该type属性。

  2. You could make your constructor private, and only allow creation via createX methods for the interfaces:您可以将构造函数设为私有,并且只允许通过接口的createX方法创建:

     export class AssignableDevice { id: number; name: string; type: string; private constructor(device: InterfaceA | InterfaceB, type: string) { this.id = device.id; this.name = device.name; this.type = type; } static createA(device: InterfaceA): AssignableDevice { return new AssignableDevice(device, "InterfaceA"); } static createB(device: InterfaceB): AssignableDevice { return new AssignableDevice(device, "InterfaceB"); } }

    Now you use the appropriate createX method for the type of the object you have.现在,您为您拥有的 object 类型使用适当的createX方法。 Since you make that choice when writing the code, TypeScript can typecheck to see that you're passing the right type of object to createX .由于您在编写代码时做出了该选择,因此 TypeScript 可以检查您是否将正确类型的 object 传递给createX

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM