Angularjs 在angular+;中以类型安全的方式使用带有自定义字段的$http侦听器;打字稿

Angularjs 在angular+;中以类型安全的方式使用带有自定义字段的$http侦听器;打字稿,angularjs,typescript,Angularjs,Typescript,我目前实现了一个angular$http拦截器,根据本地存储值向请求添加自定义头(我需要在我的应用程序中实现一个“Su”功能) 我需要在一些特殊请求上“停用”此行为(=我需要能够在每个请求的基础上配置此行为),并且我希望在调用我的$http方法时放置一个额外的配置参数来表示这一点 拦截器的外观如下所示: $httpProvider.interceptors.push((localStorageService: ng.local.storage.ILocalStorageService) =>

我目前实现了一个angular
$http
拦截器,根据本地存储值向请求添加自定义头(我需要在我的应用程序中实现一个“Su”功能)

我需要在一些特殊请求上“停用”此行为(=我需要能够在每个请求的基础上配置此行为),并且我希望在调用我的
$http
方法时放置一个额外的配置参数来表示这一点

拦截器的外观如下所示:

$httpProvider.interceptors.push((localStorageService: ng.local.storage.ILocalStorageService) => {
    return {
        request: (config: ng.IRequestShortcutConfig) => {
            var su = localStorageService.get<string>('Su');
            if(su && !("avoidSudo" in config)){
                config.headers.Su = `{ "principal": "${su}" }`;
            }
            return config;
        }
    }
});
module mymodule {
  export class SkipSudoRequestShortcutConfig implements ng.IRequestShortcutConfig { 
    // For testing purposes only
    _noSudo: boolean;
    constructor(
            public params?: any,
            public headers?: any,
            public xsrfHeaderName?: string,
            public xsrfCookieName?: string,
            public cache?: any,
            public withCredentials?: boolean,
            public data?: any,
            public transformRequest?: any,
            public transformResponse?: any,
            public timeout?: any,
            public responseType?: string
    ){
        this._noSudo = true;
    }
  }
}
var config = new SkipSudoRequestShortcutConfig();
console.log(config instanceof SkipSudoRequestShortcutConfig); // Shows true
console.log(config._noSudo); // Shows true
this.$http.get('/api/sessions/current', config)
在typescript 1.6中,此代码不会编译为
$http.get()
,第二个参数应该是
ng.IRequestShortcutConfig
,它显然不包含我的特定
avoidSudo
字段(typescript编译错误就在这里)

我可以通过将
{avoidSudo:true}
替换为
{avoidSudo:true}
来解决编译错误,但就类型安全而言,这显然并不理想

为此,我尝试创建一个新的
skipusudorequestshortcutconfig
专用类(实现
ng.IRequestShortcutConfig
)。大概是这样的:

$httpProvider.interceptors.push((localStorageService: ng.local.storage.ILocalStorageService) => {
    return {
        request: (config: ng.IRequestShortcutConfig) => {
            var su = localStorageService.get<string>('Su');
            if(su && !("avoidSudo" in config)){
                config.headers.Su = `{ "principal": "${su}" }`;
            }
            return config;
        }
    }
});
module mymodule {
  export class SkipSudoRequestShortcutConfig implements ng.IRequestShortcutConfig { 
    // For testing purposes only
    _noSudo: boolean;
    constructor(
            public params?: any,
            public headers?: any,
            public xsrfHeaderName?: string,
            public xsrfCookieName?: string,
            public cache?: any,
            public withCredentials?: boolean,
            public data?: any,
            public transformRequest?: any,
            public transformResponse?: any,
            public timeout?: any,
            public responseType?: string
    ){
        this._noSudo = true;
    }
  }
}
var config = new SkipSudoRequestShortcutConfig();
console.log(config instanceof SkipSudoRequestShortcutConfig); // Shows true
console.log(config._noSudo); // Shows true
this.$http.get('/api/sessions/current', config)
这样称呼:

$httpProvider.interceptors.push((localStorageService: ng.local.storage.ILocalStorageService) => {
    return {
        request: (config: ng.IRequestShortcutConfig) => {
            var su = localStorageService.get<string>('Su');
            if(su && !("avoidSudo" in config)){
                config.headers.Su = `{ "principal": "${su}" }`;
            }
            return config;
        }
    }
});
module mymodule {
  export class SkipSudoRequestShortcutConfig implements ng.IRequestShortcutConfig { 
    // For testing purposes only
    _noSudo: boolean;
    constructor(
            public params?: any,
            public headers?: any,
            public xsrfHeaderName?: string,
            public xsrfCookieName?: string,
            public cache?: any,
            public withCredentials?: boolean,
            public data?: any,
            public transformRequest?: any,
            public transformResponse?: any,
            public timeout?: any,
            public responseType?: string
    ){
        this._noSudo = true;
    }
  }
}
var config = new SkipSudoRequestShortcutConfig();
console.log(config instanceof SkipSudoRequestShortcutConfig); // Shows true
console.log(config._noSudo); // Shows true
this.$http.get('/api/sessions/current', config)
在拦截器中的用法如下:

        request: (config: ng.IRequestShortcutConfig) => {
            var su = localStorageService.get<string>('Su');
            console.log(config instanceof SkipSudoRequestShortcutConfig); // Shows *false* :(
            // console.log(config._noSudo); // Doesn't compile, but if executed at runtime with a breakpoint, it works and display true
            if(su && !(config instanceof mymodule.SkipSudoRequestShortcutConfig)){
                config.headers.Su = `{ "principal": "${su}" }`;
            }
            return config;
        }
请求:(config:ng.IRequestShortcutConfig)=>{
var su=localStorageService.get('su');
console.log(skipusudorequestshortcutconfig的配置实例);//显示*false*:(
//console.log(config._noSudo);//不编译,但如果在运行时使用断点执行,它将工作并显示true
if(su&!(mymodule.SkipSudoRequestShortcutConfig的配置实例)){
config.headers.Su=`{“principal”:“${Su}”}`;
}
返回配置;
}
但是一旦进入
请求
处理程序,
instanceof
测试就失败了

我想知道实现这一目标的最佳/最简单的方法是什么。 您是否认为
ng.IRequestShortcutConfig
缺少一个特殊的
config
字段,该字段允许将
$http
调用中的自定义字段放入拦截器处理程序


提前感谢,

重要的是要记住,TypeScript中的类型只是“类型助手”,在传输到javascript时会被删除。因此,您不需要实现新的$http服务。相反,您可以创建一个满足您需要的新类型

实际上,这是因为缺少角度类型定义

您可以通过创建以下接口来修复此问题

export interface IRequestShortcutConfigWithCustomConfig extends ng.IRequestShortcutConfig {
    [key: string]: any;
}
我使用的是字典样式的类型,因为它支持所有内容。但是如果不需要一般定义,可以将其更改为
avoidSudo:boolean;

export interface IHttpServiceWithCustomConfig extends ng.IHttpService {
    get<T>(url: string, config?: IRequestShortcutConfigWithCustomConfig): ng.IHttpPromise<T>;
}
使用
IHttpInterceptor

export interface IRequestConfigWithCustomConfig extends ng.IRequestConfig, IRequestShortcutConfigWithCustomConfig {

}

export interface IHttpInterceptorWithCustomConfig extends ng.IHttpInterceptor {
    request?: (config: IRequestConfigWithCustomConfig) => IRequestConfigWithCustomConfig | ng.IPromise<IRequestConfigWithCustomConfig>;
}
导出接口IRequestConfigWithCustomConfig扩展了ng.IRequestConfig、IRequestShortcutConfigWithCustomConfig{
}
使用CustomConfig扩展ng.IHttpInterceptor导出接口IHttpInterceptor{
请求?:(配置:IRequestConfigWithCustomConfig)=>IRequestConfigWithCustomConfig | ng.IPromise;
}

Hi Fred。你可能比我更了解TypScript,但我也会这么做:定义一个扩展IRequestShortcutConfig的SkipsUpsRequestShortcutConfig接口/类。你能提供更多关于“类信息不是通过角度从$http.get()调用传输到拦截器处理程序”的信息(代码+错误)吗。当然!我刚刚更新了反映我在
skipusudorequestshortcutconfig
上测试的描述。我将使skipusudorequestshortcutconfig成为一个扩展skipusudorequestshortcutconfig的接口,并包含一个可选的布尔字段
skipusudo
。将该接口的实例传递给$http应该可以正常工作,因为它扩展了KipsudorRequestShortcutConfig。我会让拦截器的请求函数以SkipudorRequestShortcutConfig实例作为参数。我不会使用instanceof check,而是简单地测试
config.skipSudo
是否真实。根本没有测试:我从未将TypScript用于Angular 1,也没有使用TS的经验。我不能将
skipusudorequestshortcutconfig
实例作为
请求
回调的参数,因为在大多数情况下,我会一直将标准的
ng.IRequestShortcutConfig
传递给
$http
调用。您是否可以不使用拦截器而直接重写/继承普通的
$httpProvider
>并传递普通请求,但是否将您的
SkipSudoRequestShortcutConfig
检查添加到其中?