[英]Typescript interface merging to make an external lib's interface property more specific
[英]Typescript interface merging to make return type more specific
我想使用自定義類型定義來使 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');
好吧,使用當前版本的express.js 類型定義,我發現您可以使用此代碼增強get
功能。
custom.d.ts :
import { MyClass } from './MyClass';
declare module 'express-serve-static-core' {
export interface IRouterMatcher<T> {
(name: 'foo'): MyClass;
}
}
解釋:
不幸的是,這是一個有點駭人聽聞的解決方案,因為您對看似無關的接口使用聲明合並。 您需要這樣做,因為您不能像這個答案一樣使用全局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. :(
}
}
我認為更清潔的解決方案是更改絕對類型類型。 它的工作方式類似於在前面提到的問題中如何完成Request
對象的擴充( get
簽名需要表示為可以與您的自定義定義類型合並的接口)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.