我想使用自定义类型定义来使Express API中的返回类型更具体。我们正在使用app.set
和app.get
来保留应用程序中的全局对象。
app.get('foo')
会返回特定的类MyClass
,因此我想使用TypeScript表达这一事实,以避免必须明确转换。
包含的app.get
中index.d.ts
的现有定义如下:
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');
答案 0 :(得分: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 :(
}
}
因为如果您仔细查看输入内容,您会发现set
中的get
和Express.Application
方法被覆盖并使用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
签名需要表示为可以与自定义类型合并的接口)