【问题标题】:Typescript interface merging to make return type more specificTypescript 接口合并以使返回类型更具体
【发布时间】:2018-06-07 21:27:24
【问题描述】:

我想使用自定义类型定义来使 Express API 中的返回类型更加具体。我们使用app.setapp.get 将全局对象保留在我们的应用程序中。

app.get('foo') 返回一个特定的类MyClass,所以我想用 TypeScript 来表达这个事实,以避免必须显式转换。

包含的index.d.tsapp.get 的现有定义如下所示:

get: ((name: string) => any) & IRouterMatcher<this>;

在我的自定义类型定义中,我添加了以下内容:

import { MyClass } from '../MyClass';

declare global {
  namespace Express {
    export interface Application {
      get (name: 'foo'): MyClass;
      // also tried this to conform to existing structure:
      // get: ((name: 'foo') => MyClass);
    }
  }
}

但是在这两种情况下,app.get('foo') 的返回类型仍然是any

在执行以下操作时是否可以隐式具有正确的类型……:

let myObject = app.get('foo');

…为了避免不得不写:

let myObject: MyClass = app.get('foo');

【问题讨论】:

    标签: typescript express interface


    【解决方案1】:

    嗯,使用当前版本的express.js type definitions,我发现您可以使用此代码扩充get 函数。

    custom.d.ts

    import { MyClass } from './MyClass';
    
    declare module 'express-serve-static-core' {
      export interface IRouterMatcher<T> {
        (name: 'foo'): MyClass;
      }
    }
    

    解释:

    不幸的是,这是一个有点骇人听闻的解决方案,因为您将declaration merging 用于看似不相关的界面。 您需要这样做,因为您不能像在 this 中那样使用全局 Express 命名空间扩充@ 答案:

    declare namespace Express {  
      export interface Application {
        get(name: 'foo'): MyClass; //doesn't work :(
      }
    }
    

    因为如果您仔细查看类型,您会发现Express.Application 中的getset 方法被使用extends 关键字覆盖

    export interface Application extends IRouter, Express.Application {
      ...
      set(setting: string, val: any): Application;
      get: ((name: string) => any) & IRouterMatcher<this>;
      ...
    }
    

    您也不能增加 getset 方法,因为如果您更改属性类型,则声明合并不起作用。

    declare module 'express-serve-static-core' {
      export interface Application {
        get: ((name: string) => any) &
          IRouterMatcher<this> &
          ((name: 'foo') => MyClass);
          //Error: 'Error: Subsequent variable declarations must have the same type. :(
      }
    }
    

    我认为更简洁的解决方案是更改DefinitelyTyped typing。它的工作方式类似于在previously 提到的问题中如何增加Request 对象(get 签名需要表示为可以与您的自定义类型合并的接口)

    【讨论】:

    • 非常感谢您的详细解释和建议——非常有帮助!
    猜你喜欢
    • 2011-02-10
    • 1970-01-01
    • 2011-07-01
    • 1970-01-01
    • 2019-01-15
    • 1970-01-01
    • 1970-01-01
    • 2011-04-03
    • 2016-03-15
    相关资源
    最近更新 更多