在声明表示正在接收的对象的参数类型时,我是否应该手动解析从服务器接收到的 JSON 字符串?
Should I manually parse a JSON string received from a server while the type of the parameter which represents the object being received is declared?
我正在 Observable 的缩减函数中处理 Http 结果。当参数 jwt
的类型设置为 { id: string, auth_token: string, expires_in }
时, jwt
参数变成了 string
。我以为 TypeScript 会自动解析。我必须自己做 JSON.parse(JSON.stringify(jwt))
吗?
.mergeMap((jwt: { id: string, auth_token: string, expires_in }) => {})
如果 jwt(JSON) 对象是通过 Http
从 HttpModule
@angular/http
中检索到的,则必须将其解析为 JSON
例如:
import { Http } from '@angular/http';
....
constructor(
private http: Http
...
) {}
this.http.get(url)
.map((res: any) => {
return res.json();
}).subscribe( (jwt: any) => {
//you got jwt in JSON format
});
如果你使用 HttpClient
from HttpClientModule
@angular/common/http
(Angular > 4.3.x) 你不需要解析接收到的数据,因为它已经完成了。
import { HttpClient } from '@angular/common/http';
....
constructor(
private http: HttpClient
...
) {}
this.http.get<any>(url)
.subscribe((jwt: any) => {
//you got jwt in JSON format
})
类型检查外部代码
TypeScript 源代码与在 run-time 处执行的 JavaScript 输出之间没有任何关系。如果编译类型匹配 run-time 类型,TypeScript 仅在捕获 compile-time 错误时有效。
通常情况下,这不是问题。但是在您调用外部代码的场景中(即 AJAX 调用从服务器获取数据),无法保证响应将是您期望的类型。所以在这些情况下一定要小心。
你的具体例子
我怀疑你的代码有一个类型为 any
的变量 jwt
而你只是将该类型分配给 { id: string, auth_token: string, expires_in }
而实际上 jwt
是字符串类型就 javascript 而言。
在这种情况下,您已经找到了解决方案,JSON.parse(str)
。这会将 json 字符串转换为 javascript 对象。
现在你有了一个对象,你可以使用 duck typing 来推断 run-time 类型,并让打字稿通过 type guards.[=18= 知道 compile-time 的类型]
解决方案
function isDate(obj: any): obj is Date {
return typeof obj === 'object' && 'toISOString' in obj;
}
function isString(obj: any): obj is string {
return typeof obj === 'string';
}
interface JWT {
id: string;
auth_token: string;
expires_in: Date;
}
function isJwt(obj: any): obj is JWT {
const o = obj as JWT;
return o !== null
&& typeof o === 'object'
&& isString(o.id)
&& isString(o.auth_token)
&& isDate(o.expires_in);
}
function print(jwt: any) {
if (typeof jwt === 'string') {
try {
jwt = JSON.parse(jwt);
} catch (e) {
console.error(`String is not JSON: ${jwt}`);
}
}
if (isJwt(jwt)) {
console.log(`Found jwt: ${jwt.id} ${jwt.auth_token} ${jwt.expires_in}`);
} else {
console.error(`Object is not of type jwt: ${jwt}`);
}
}
print(42);
print('failing');
print(null);
print(undefined);
print({});
print({ id: 'id01', auth_token: 'token01', expires_in: new Date(2018, 11, 25) });
游乐场
尝试 运行 TS Playground 上的代码,看看它如何检查 run-time 上的对象。
我正在 Observable 的缩减函数中处理 Http 结果。当参数 jwt
的类型设置为 { id: string, auth_token: string, expires_in }
时, jwt
参数变成了 string
。我以为 TypeScript 会自动解析。我必须自己做 JSON.parse(JSON.stringify(jwt))
吗?
.mergeMap((jwt: { id: string, auth_token: string, expires_in }) => {})
如果 jwt(JSON) 对象是通过 Http
从 HttpModule
@angular/http
中检索到的,则必须将其解析为 JSON
例如:
import { Http } from '@angular/http';
....
constructor(
private http: Http
...
) {}
this.http.get(url)
.map((res: any) => {
return res.json();
}).subscribe( (jwt: any) => {
//you got jwt in JSON format
});
如果你使用 HttpClient
from HttpClientModule
@angular/common/http
(Angular > 4.3.x) 你不需要解析接收到的数据,因为它已经完成了。
import { HttpClient } from '@angular/common/http';
....
constructor(
private http: HttpClient
...
) {}
this.http.get<any>(url)
.subscribe((jwt: any) => {
//you got jwt in JSON format
})
类型检查外部代码
TypeScript 源代码与在 run-time 处执行的 JavaScript 输出之间没有任何关系。如果编译类型匹配 run-time 类型,TypeScript 仅在捕获 compile-time 错误时有效。
通常情况下,这不是问题。但是在您调用外部代码的场景中(即 AJAX 调用从服务器获取数据),无法保证响应将是您期望的类型。所以在这些情况下一定要小心。
你的具体例子
我怀疑你的代码有一个类型为 any
的变量 jwt
而你只是将该类型分配给 { id: string, auth_token: string, expires_in }
而实际上 jwt
是字符串类型就 javascript 而言。
在这种情况下,您已经找到了解决方案,JSON.parse(str)
。这会将 json 字符串转换为 javascript 对象。
现在你有了一个对象,你可以使用 duck typing 来推断 run-time 类型,并让打字稿通过 type guards.[=18= 知道 compile-time 的类型]
解决方案
function isDate(obj: any): obj is Date {
return typeof obj === 'object' && 'toISOString' in obj;
}
function isString(obj: any): obj is string {
return typeof obj === 'string';
}
interface JWT {
id: string;
auth_token: string;
expires_in: Date;
}
function isJwt(obj: any): obj is JWT {
const o = obj as JWT;
return o !== null
&& typeof o === 'object'
&& isString(o.id)
&& isString(o.auth_token)
&& isDate(o.expires_in);
}
function print(jwt: any) {
if (typeof jwt === 'string') {
try {
jwt = JSON.parse(jwt);
} catch (e) {
console.error(`String is not JSON: ${jwt}`);
}
}
if (isJwt(jwt)) {
console.log(`Found jwt: ${jwt.id} ${jwt.auth_token} ${jwt.expires_in}`);
} else {
console.error(`Object is not of type jwt: ${jwt}`);
}
}
print(42);
print('failing');
print(null);
print(undefined);
print({});
print({ id: 'id01', auth_token: 'token01', expires_in: new Date(2018, 11, 25) });
游乐场
尝试 运行 TS Playground 上的代码,看看它如何检查 run-time 上的对象。