web-dev-qa-db-ja.com

Typescriptの関数のジェネリック戻り値の型

私はtsに不慣れですが、Javaのジェネリックスの概念について少し学びました。クエリは、searchTrack、searchAlbum、searchArtistの3つの関数があることです。

  searchTrack(query: string): Observable<Track[]> {
    return this.search(query, 'track');
  }

  searchArtist(query: string): Observable<Artist[]> {
    return this.search(query, 'artist');
  }

  searchAlbum(query: string): Observable<Album[]> {
    return this.search(query, 'album');
  }

クエリとエンティティのタイプを受け取り、特定のエンティティタイプのコレクションのObservableを返す、このクラスの一般的な関数 'search'が必要です。私はここで立ち往生しています。ジェネリックを操作して、関数のジェネリック戻り値の型を指定するにはどうすればよいですか。

search(query: string, type: string): Observable<Array<T>> {
 return this.query(`/search`, [
   `q=${query}`,
   `type=${type}`
 ]);
}

これを達成する方法はありますか?

8
Param Singh

[]の代わりにArrayクラスを使用してみてください。また、検索関数でジェネリックTタイプを定義します。

search<T>(query: string, type: string): Observable<Array<T>> {
 return this.query(`/search`, [
   `q=${query}`,
   `type=${type}`
 ]);
}

あなたはそれをこのように呼ぶことができるはずです:

let result = search<Artist>('someQuery', 'artist');

TypeScriptのジェネリックスの詳細については、ハンドブックのジェネリックスの章を参照してください ここ

5
toskv

@toskvが回答したように、ジェネリック型をメソッドシグネチャに追加できますが、コンパイラには型を推測する方法がないため、追加する必要があります。

myObj.search<Track>(query, "track");

ただし、次のようなことができます。

interface MyObservableClass {}

interface MyObservableClassCtor<T extends MyObservableClass> {
    new (): T;
    getType(): string;
}

class Artist implements MyObservableClass {
    static getType(): string {
        return "artist";
    }
}

class Album implements MyObservableClass {
    static getType(): string {
        return "album";
    }
}

class Track implements MyObservableClass {
    static getType(): string {
        return "track";
    }
}

class Searcher {
    search<T extends MyObservableClass>(ctor: MyObservableClassCtor<T>, query: string): Observable<T[]> {
        return this.query(`/search`, [
            `q=${query}`,
            `type=${ ctor.getType() }`
        ]);
    }
}

let searcher: Searcher = ...;

searcher.search(Track, "...");

そして、コンパイラは、クラス(/ ctor)を提供することにより、Tが何であるかを推測できます。

2
Nitzan Tomer

あなたはオーバーロードでそれを行うことができます:

class A {
    search<T>(query: string, type: "Track"): Observable<Track[]>;
    search<T>(query: string, type: "Artist"): Observable<Artist[]>;
    search<T>(query: string, type: "Album"): Observable<Album[]>;
    search<T>(query: string, type: string): Observable<T[]>;
    search<T>(query: string, type: string): Observable<T[]> {
        return null;
    }
}

これにより、正しいタイプが得られます。

var observable = x.search("test", "Track");

そして、これは互換性のないオブジェクトでコンパイルエラーを引き起こします:

var observableError: Observable<Album[]> = x.search("test", "Track");
1
yeerk