在声明表示正在接收的对象的参数类型时,我是否应该手动解析从服务器接收到的 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) 对象是通过 HttpHttpModule @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 上的对象。