具有泛型的函数,该泛型返回具有.d.ts中的泛型的类

时间:2017-04-11 15:10:37

标签: typescript typescript-typings

我尝试修改常规用法的代码,用于声明生成(或手动编写声明)。代码是这样的:

function createClass<T>( data: T )
{
    abstract class Internal<T2>
    {
        public constructor( arg: T2 )
        {
            console.log( data, arg );
        }

        protected abstract method( arg: T ): void;
    }

    return Internal;
}

问题是我应该指定函数结果的类型,但我不知道如何做到这一点 - 我尝试了不同的选项,但都没有。

加了:

这个小例子可能不完全清楚,所以我添加了出现问题的原始代码:

原始代码,我正试图变成一个包:https://gist.github.com/Avol-V/1af4748f4b0774a999311c92b6dc1631

您可以在那里找到small-redux的代码:https://github.com/m18ru/small-redux/blob/master/src/createStore.ts

您可以在那里找到preact的代码:https://github.com/developit/preact/blob/master/src/preact.d.ts

问题是我不想为创建的类的每次使用指定TState类型 - 它不能在创建的类上更改,因此它是不正确的。

加了:

所以,我没有找到任何解决方案,没有在创建的类的泛型中明确指定T(除了T2 - class Internal<TInternal, T2>)。我的结果代码如下:https://github.com/m18ru/preact-small-redux/blob/85c143e851b92c44861dc976ce6ef89bcda2c884/src/index.ts

如果你只想编写一个返回带泛型的类的函数,你可以像@baryo建议的那样(通过一些清理):

declare abstract class AbstractInternal<T>
{
    public abstract method( arg: T ): void;
}

function createClass(): typeof AbstractInternal
{
    abstract class Internal<T> implements AbstractInternal<T>
    {
        public abstract method( arg: T ): void;
    }

    return Internal;
}

const A = createClass();

class B extends A<string>
{
    public method( arg: string ): string
    {
        return 'Hello ' + arg;
    }
}

1 个答案:

答案 0 :(得分:2)

您在函数内创建的所有内容都包含在其中,包括类型。因此,您至少需要定义类型。也许以下内容对您有所帮助:

interface IInternal<T> {
    method(arg: T): void;
}

type InternalCtor<T> = new (param: T) => IInternal<T>;

function createClass<T>(data: T): InternalCtor<T>
{
    abstract class Internal<T> implements IInternal<T>
    {
        public constructor( arg: T )
        {
            console.log( data, arg );
        }

        public abstract method( arg: T ): void;
    }

    return Internal as InternalCtor<T>;
}

class A extends createClass<number>(1) {
    public method() {
        console.log('hello');
    }
}

const z = new A(2);  // 1 2

编辑: 你提到你感兴趣的是泛型方法将返回一个泛型类 - 它对于打字变得有点棘手,但我们可以让Typescript本身推断我们需要的一切。

function createClass<T>(data: T)
{
    // directly return a new class with a different generic type.
    //  notice that you can't return an abstract class.
    return class Internal<U>
    {
        public constructor( arg: U )
        {
            console.log( data, arg );
        }

        public method(arg: T): void { console.log(arg); }
    }
}



// first generic type (number) is for the function, then the second generic type (string) is for the returned class.
class A extends createClass<number>(1)<string> {

}

const z = new A('zzz');   // 1 zzz
z.method(2); // 2

编辑2: 它与你正在寻找的有点不同,但我认为更好的做法将是以下(类似于@Diullei所建议的):

abstract class AbstractInternal<T> {
    public abstract method(arg: T): void;
}

type InternalCtor<T> = new (param: T) => AbstractInternal<T>;

function createClass<T, U>(data: T): InternalCtor<U> {
    abstract class Internal<U> implements AbstractInternal<U>
    {
        public constructor(arg: T) {
            console.log(data, arg);
        }

        public abstract method(arg: U): void;
    }

    return Internal as any as InternalCtor<U>;
}

class A extends createClass<number, string>(1) {
    public method(arg: string) { // now I need to implement this to avoid a compilation error
        console.log(`hello ${arg}`);
    }
}

const z = new A('arg'); // 1 "arg""
z.method('arg2'); // "hello arg2""