指定没有中间变量的返回类型

时间:2016-12-25 17:14:00

标签: typescript

有时打字稿无法推断lambda或方法的返回类型,我想手动指定它以获得类型安全。

问题出现在例如使用promises或更复杂的回调时(例如使用parsimmon解析库)。

我没有找到一种方法来指定返回变量的类型来获取类型检查,除非通过创建局部变量:

interface ITest {
    x: number;
    y: string;
}

// type checks, i'd prefer it doesn't
function f1() {
    return {x:5} as ITest;
}

// type checks, i'd prefer it doesn't
// (I understand it's a cast, just to show also that doesn't help)
function f2() {
    return <ITest>{x:5};
}

// correctly fails to type-check
function f3() {
    const x: ITest = {x:5};
    return x;
}

还有另一种方法可以在不创建局部变量的情况下进行类型检查吗?我当然知道我可以输入function f4(): ITest,但我的用例看起来更像是这样:

return P.string(" for ")
    .then(P.takeWhile(c => c !== ' ').skip(P.string(" in ")))
    .chain(value => P.takeWhile(c => c !== ' ')
           .chain(array => parseNgOptionsTrackBy().atMost(1)
                  .map(trackBy => {
                      // variable created solely for type-checking
                      const r: NgOptionsData = {
                          select: expressions.select,
                          label: expressions.label,
                          value: value,
                          array: array,
                          trackexpr: trackBy ? trackBy[0] : undefined
                      };
                      return r;
                  })));

或:

return new Promise((resolve, reject) => {
    // some code, then variable created solely for type-checking
    const result: ViewInfo = {
        fileName: fileName,
        ngModuleName: ngModuleName,
        controllerName: controllerName,
        controllerViewInfos: viewInfos};
    resolve(result);
});

换句话说,我深入一些lambda并指定一个返回类型并不那么简单。

更新我看到有些人怀疑打字稿实际上无法推断resolve的承诺。幸运的是我的应用程序是OSS。我做了一个提交,在一些分支中演示了这个问题: https://github.com/emmanueltouzery/ng-typeview/tree/so_question

检查the last commit on that branch。正如你所看到的,我从我正在填充的结构中删除了一个字段(我想要一个构建错误!!)但它构建得很好。我做了指定函数的返回类型Promise<ControllerScopeInfo>This is type-unsafe。 如果要构建,则必须运行npm install,然后tsc。虽然大概你可以检查源和tsconfig并且信任我在建筑物上。

3 个答案:

答案 0 :(得分:1)

你的意思是:

return new Promise((resolve, reject) => {
    resolve({
        fileName: fileName,
        ngModuleName: ngModuleName,
        controllerName: controllerName,
        controllerViewInfos: viewInfos
    } as ViewInfo);
});

修改

这很奇怪,可能是一个错误,因为如果添加一个可选属性:

interface ViewInfo {
    fileName: string;
    ngModuleName: string;
    controllerName: string;
    controllerViewInfos: ViewInfo[];
    dummy?: any;
}

然后做:

return Promise.resolve({
    fileName: "fileName 2",
    ngModuleName: "ngModuleName 2",
    controllerName: "controllerName 2",
    dummy: 3
});

你会收到错误:

  

输入'Promise&lt; {fileName:string; ngModuleName:string;   controllerName:string;假人:数字; }&GT;”不能分配给类型   '诺言'。

     

输入'{fileName:string; ngModuleName:string; controllerName:   串;假人:数字; }'不能分配给'ViewInfo'类型。

     

类型'{fileName:string;}中缺少属性'controllerViewInfos';   ngModuleName:string; controllerName:string;假人:数字; }”。

它有可能是设计的,但我现在想不出一个理由。尝试提交问题,如果你这样做,请分享链接。

同时,您可以为要返回的这些类型创建工厂函数:

function viewInfoFactory(fileName: string, ngModuleName: string, controllerName: string, controllerViewInfos: ViewInfo[]): ViewInfo {
    return {
        fileName,
        ngModuleName,
        controllerName,
        controllerViewInfos
    }
}

在该功能中,您将获得您所追求的类型安全性,同时,根据您的代码,它可以使其更具可读性。

答案 1 :(得分:1)

根据要求

在上面的一个例子中:

    function x() /*: Promise<{}>*/ {
        // declared as Promise<{}>    
        return new Promise((resolve, reject) => {                
            // ViewInfo assignable to {} 
            resolve(
                <ViewInfo>  {
                fileName: fileName,
                ngModuleName: ngModuleName,
                controllerName: controllerName,
                controllerViewInfos: viewInfos}
            );
        })
    };

推断函数是

()=> Promise<{}>  

由于:

CORS Generic ,并希望在构造函数中指定 T
或默认为Promise&lt; {}&gt;
解析ViewInfo也是合法的 基于Promise
可分配给{}

这可以解释为什么示例代码按设计工作

答案 2 :(得分:0)

您可以声明某些承诺的返回类型,例如Promise<string>

function returnStringPromise(): Promise<string> {
    return new Promise((resolve, reject) => {
        resolve("string");
    })
}

return <Promise<string>> new Promise((resolve, reject) => resolve("string"));

return new Promise((resolve, reject) => resolve("string")) as Promise<string>;