web-dev-qa-db-ja.com

ジェネリック型のプロパティを取得するにはどうすればよいですか?

抽象クラスがあり、そのメソッドにジェネリック型のアイテムを渡します。次に、このアイテムのプロパティを取得する必要があります。それを正しく行うにはどうすればよいですか?

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> {
        ...
    }
11
Green176

コードでは、クラスで使用されるすべての型Tidプロパティがあると想定しています。

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);
}
9
Aluan Haddad

値をフェッチする前にitem.hasOwnProperty( 'id')を使用できます。

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

1
Surender Kherwa