Typescript 接口合并以使返回类型更具体

Posted

技术标签:

【中文标题】Typescript 接口合并以使返回类型更具体【英文标题】:Typescript interface merging to make return type more specific 【发布时间】: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');

【问题讨论】:

【参考方案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 签名需要表示为可以与您的自定义类型合并的接口)

【讨论】:

非常感谢您的详细解释和建议——非常有帮助!

以上是关于Typescript 接口合并以使返回类型更具体的主要内容,如果未能解决你的问题,请参考以下文章

在 Typescript 中,为数组定义一个类型,其中第一个元素比其他元素更具体

TypeScript学习笔记

如何在TypeScript中使用类型保护

使 arrayList.toArray() 返回更具体的类型

5种在TypeScript中使用的类型保护

TypeScript 中具有泛型类型参数的泛型类型的替代方案