Typescript 中函数的通用返回类型

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/37386265/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-21 03:31:00  来源:igfitidea点击:

Generic return type of function in Typescript

functiongenericstypescript

提问by Param Singh

I'm new to ts but I've learnt a little about the concept of generics in java. The query is that I have three functions : searchTrack, searchAlbum, searchArtist

我是 ts 的新手,但我对 java 中的泛型概念有了一些了解。查询是我有三个函数:searchTrack、searchAlbum、searchArtist

  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');
  }

I want a general function 'search' in this class that takes the query and the type of entity and returns an Observable of collection of a specific entity type. I'm stuck here. How can I work with generics to specify a generic return type of a function.

我想要这个类中的通用函数“搜索”,它接受查询和实体类型,并返回特定实体类型集合的 Observable。我被困在这里。我如何使用泛型来指定函数的泛型返回类型。

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

Is there any way I can achieve this?

有什么办法可以实现这一目标吗?

采纳答案by toskv

Try using the Arrayclass instead of []. Also define a generic T type on the search function.

尝试使用Array类而不是 []。还要在搜索函数上定义一个通用的 T 类型。

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

You should be able to call it like this:

你应该可以这样称呼它:

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

You can find more about generics in typescript in the Generics chapter in the handbook here.

您可以在此处手册的泛型一章中找到有关打字稿中泛型的更多信息。

回答by Nitzan Tomer

As @toskv answered, you can add a generics type to the method signature, but the compiler has no way of inferring the type so you'll have to add it:

正如@toskv 回答的那样,您可以向方法签名添加泛型类型,但编译器无法推断类型,因此您必须添加它:

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

However, you can do something like:

但是,您可以执行以下操作:

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, "...");

And then the compiler can infer what the Tis by providing it with the class (/ctor).

然后编译器可以T通过为它提供类 (/ctor)来推断它是什么。

回答by yeerk

You can do it with overloads:

你可以用重载来做到这一点:

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;
    }
}

Which will give you the correct type:

这将为您提供正确的类型:

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

And this will give a compile error on incompatible objects:

这将在不兼容的对象上产生编译错误:

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