【问题标题】:How to get property of generic type?如何获取泛型类型的属性?
【发布时间】:2018-02-16 10:47:04
【问题描述】:

我有一个抽象类,在它的方法中我传递了一个泛型类型的项目。接下来我需要获取这个item的属性,如何正确做呢?

export abstract class BaseService<T> {
    ...
    public saveItem(item: T) {
        ...
        if (item.id <=== here I got error ) {
        }
        ...
    }

    export class ClusterItem {
        id: number;
        ...
     }

    export class ClustersService extends BaseService<ClusterItem> {
        ...
    }

【问题讨论】:

  • 您可以使用Type Guards 在尝试访问某些属性或通过括号符号item['id'] 访问之前检查类型
  • 也许T extends { id: number },将泛型类型限制为具有该属性的事物。

标签: typescript generics


【解决方案1】:

您可以在尝试获取值之前使用 item.hasOwnProperty('id')。

参考:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty

【讨论】:

    【解决方案2】:

    您的代码假定与您的类一起使用的每个类型 T 都可能具有 id 属性。

    正如 Jon Sharpe 在他对您的问题的评论中指出的那样,正确的方法,无论是在类型安全性和表达性方面,都是将此假设声明为类型约束,使其明确并为类型检查器所知。

    这样做的方法是在泛型类型参数上使用类型约束语法。

    例如,你可以写

    export interface MayHaveId {
      id?: number; // you can use any type, number is just an example
    }
    
    export abstract class BaseService<T extends MayHaveId> {
      saveItem(item: T) {
        if (item.id !== undefined) {
          console.log(item.id);
        }
      }
    } 
    

    这里我们定义了一个接口来使代码更具可读性,但类型字面量也可以。

    请注意,id 属性声明为可选,因为您的逻辑不要求它具有值。

    如果您只打算将基类与具有id 的类型参数一起使用,那么您应该将该属性设为必需。这将使代码更易于理解,并会在编译时捕获更多错误,方法是首先确保它只与此类类型一起使用。

    Shahbaaz 在评论中询问了动态属性。

    我们可以通过使用参数泛型类型来定义具有动态属性的类型

    type WithProperty<K extends string, V = {}> = {
      [P in K]: V
    }
    

    我们可以消费这种类型

    function withProperty<T, K extends string, V> (x: T, properties: WithProperty<K, V>) {
      return Object.assign(x, properties);
    }
    

    【讨论】:

    • 如果要求属性名称将与对象一起发送,即属性名称是动态的,该怎么办
    • @Shahbaaz 有点跑题了,但我添加了一个例子。
    猜你喜欢
    • 1970-01-01
    • 2015-02-15
    • 2012-12-17
    • 2020-01-29
    • 2019-07-27
    • 2015-07-28
    • 1970-01-01
    • 2019-05-16
    • 1970-01-01
    相关资源
    最近更新 更多