TypeScript错误TS2339,但属性确实存在
问题描述:
当我使用gulp编译下面的TypeScript代码时,我得到:错误TS2339:属性'accessToken'在类型'Response'上不存在。 Visual Studio 2015中的ErrorList窗口报告data.accessToken
和data.expiryDate
的错误。当我注释引用变量data
的两行时,代码将运行,调试程序显示data
不是“响应”类型,而实际上包含属性data.accessToken
和data.expiryDate
。在Visual Studio中,当我将鼠标悬停在变量data
上时,工具提示正确报告data
的类型为any
。TypeScript错误TS2339,但属性确实存在
为什么TypeScript无法正确传输,我该如何解决问题?为什么TypeScript认为data
的类型是Response
而不是any
? 我正在使用TypeScript 2.1.4。 http.fetch使用奥里利亚获取客户documented here
/// <reference path="../typings/index.d.ts" />
import 'fetch';
import {HttpClient, json} from 'aurelia-fetch-client';
import {inject} from 'aurelia-framework';
import {BearerToken} from './common/bearer-token';
export class ApiToken
{
...
public refreshToken(): Promise<BearerToken>
{
let token: BearerToken = new BearerToken();
token.accessToken = "no_data";
token.expiryDate = Date.now();
return this.http.fetch('/Account/getToken')
.then(response => response.json())
.then(data =>
{
console.log('ApiToken.refreshToken returned data: ' + data);
// The next two lines cause build errors.
// When commented out the code runs and the debugger shows that
// data.accessToken and data.expiryDate do exist on data.
token.accessToken = data.accessToken;
token.expiryDate = data.expiryDate;
return token;
})
.then((t) => { return this.saveToken(t) });
}
...
}
这里是我的tsconfig.json文件:
{
"compileOnSave": false,
"compilerOptions": {
"rootDir": "src",
"outDir": "dist",
"sourceMap": true,
"target": "es5",
"module": "amd",
"declaration": false,
"noImplicitAny": false,
"removeComments": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"moduleResolution": "node",
"lib": ["es2015", "dom"],
"baseUrl": "./",
"paths": {
"src/*": ["src/*"]
}
},
"filesGlob": [
"./src/**/*.ts",
"./test/**/*.ts",
"./typings/index.d.ts",
"./custom_typings/**/*.d.ts",
"./jspm_packages/**/*.d.ts"
],
"exclude": [
"node_modules",
"jspm_packages",
"dist",
"build",
"test"
],
"atom": {
"rewriteTsconfig": false
}
}
我试着用以下指定的data
的类型,但它并没有解决问题,虽然该错误消息是不同的,两者如下所示:
interface TokenResult
{
accessToken: string;
expiryDate: string;
}
....
public refreshToken(): Promise<BearerToken>
{
let token: BearerToken = new BearerToken();
token.accessToken = "no_data";
token.expiryDate = new Date(Date.now().toString());
return this.http.fetch('/Account/getToken')
.then(response => response.json())
.then((data: TokenResult) =>
{
console.log('ApiToken.refreshToken returned data: ' + data);
token.accessToken = data.accessToken;
token.expiryDate = new Date(data.expiryDate);
return token;
})
.then((t) => { return this.saveToken(t) });
}
而错误是:
error TS2345: Argument of type '(data: TokenResult) => BearerToken' is not assignable to parameter of type '(value: Response) => BearerToken | PromiseLike<BearerToken>'.
Types of parameters 'data' and 'value' are incompatible.
Type 'Response' is not assignable to type 'TokenResult'.
Property 'accessToken' is missing in type 'Response'.
答
我从gitter的贡献者那里找到了答案。一个演员阵容到any
,然后演员阵容到TokenResult
做的伎俩,如下...
return this.http.fetch('/Account/getToken')
.then(response => response.json())
.then((data: any) =>
{
console.log('ApiToken.refreshToken returned data: ' + data);
token.accessToken = (<TokenResult>data).accessToken;
token.expiryDate = (<TokenResult>data).expiryDate;
return token;
})
.then((t) => { return this.saveToken(t) });
有同样的问题。宣布(数据:任何)为我们做了诀窍。在我们的情况下,没有必要进一步演员 – eMBee