TypeScript函数返回函数集

时间:2018-03-03 15:18:19

标签: typescript signature

我试图将以下vanilla JS代码移植到TypeScript,以更好地定义所有函数的返回类型。此代码导出单个函数resource。调用时,resource返回包含其他函数的对象。

在构造函数中初始化的Demo类中使用资源时,类型签名似乎消失了。一种方法是为resource定义一个接口。但是,我似乎无法为resource 定义界面,而无需重复 doThingOne()doThingTwo()中已定义的参数。我目前的尝试都让我不得不复制签名。我该如何解决这个问题以保持干燥?

function resource(someVar) {

    function doThingOne(p1 = '') {
        return Promise.resolve('thing one ' + someVar + p1);
    }

    function doThingTwo(p1 = '') {
        return Promise.resolve('thing two ' + someVar + p1);
    }

    return {
        doThingOne,
        doThingTwo
    };
}

class Demo {
    resource1;

    constructor() {
        this.resource1 = resource('resource1');
    }
}

const issues = new Demo();
issues.resource1 // no type information for resource1

2 个答案:

答案 0 :(得分:1)

您基本上想要将成员键入为函数的结果类型。

执行此操作的最简单方法是,让编译器根据赋值推断出它:

class Demo {
    constructor(name: string, public resource1 = resource(name)) {

    }
}

const issues = new Demo("resource1");
issues.resource1 // correct type

如果这不可行,您可以通过以下两种方式之一获取返回类型:

在Typescript 2.8中

使用ReturnType<T>条件类型。 (2.8在撰写本文时未发布,但将于2018年3月发布,您可以通过npm install -g typescript@next获取)

class Demo {
    public resource1: ReturnType<typeof resource>
    constructor() {

    }
}

Pre 2.8

您可以使用辅助函数和虚拟变量从函数中提取类型:

// Dummy function, just used to extract the result type of the function passed as the argument
function typeHelper<T>(fn: (...p:any[]) => T): T{
    return null as T;
}
// Dummy variable, null at runtime, but it's type is inferred as the result of the `resource function
let dummy = typeHelper(resource);

// Create a type definition based on the type of dummy
type resourceReturnType = typeof dummy;


class Demo {
    public resource1: resourceReturnType
    constructor() {

    }
}

答案 1 :(得分:0)

一旦存在可以保持状态的类实例(在someVar函数的情况下为resource),就不需要工厂函数:

class Resource {
    constructor(private someVar: string);

    doThingOne(p1 = '') {
        return Promise.resolve('thing one ' + this.someVar + p1);
    }

    doThingTwo(p1 = '') {
        return Promise.resolve('thing two ' + this.someVar + p1);
    }
}

class Demo {
    resource1 = new Resource('resource1');
}

如果Demo不应该做任何其他事情,可以将它们重构为单个课程。