Typescript 接口合并以使返回类型更具体
Posted
技术标签:
【中文标题】Typescript 接口合并以使返回类型更具体【英文标题】:Typescript interface merging to make return type more specific 【发布时间】:2018-06-07 21:27:24 【问题描述】:我想使用自定义类型定义来使 Express API 中的返回类型更加具体。我们使用app.set
和app.get
将全局对象保留在我们的应用程序中。
app.get('foo')
返回一个特定的类MyClass
,所以我想用 TypeScript 来表达这个事实,以避免必须显式转换。
包含的index.d.ts
中app.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
中的get
和set
方法被使用extends
关键字覆盖。
export interface Application extends IRouter, Express.Application
...
set(setting: string, val: any): Application;
get: ((name: string) => any) & IRouterMatcher<this>;
...
您也不能增加 get
和 set
方法,因为如果您更改属性类型,则声明合并不起作用。
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 中,为数组定义一个类型,其中第一个元素比其他元素更具体