【问题标题】:How can I apply a Interface to a HTTP response如何将接口应用于 HTTP 响应
【发布时间】:2020-01-11 13:54:01
【问题描述】:

在我的应用中,我收到来自 API 的响应,该响应具有以下模式。

export interface IApiResponseBody<T = any> {
    Error?: string;
    Message?: string;
    RowsAffected?: number;
    Success?: boolean;
    Data?: T;
    RowCount?: number;
}

我没有问题将接口分配给响应,然后我可以访问响应中的元素。我遇到的问题是当我尝试通过TData 分配接口时,就像

let myData: IApiResponseBody<IPerson>  = {
    Success: true,
    Error: "",
    Message: "",
    RowsAffected: 9,
    Data: [{name: 'Steve', age: 26, gender : 'male'},
            {name: 'Susan', age: 21, gender : 'female'},
            {name: 'SteveFrank', age: 29, gender : 'male'}]}

无论我使用 Data 中的数组还是简单的 Doc,都会出现错误。

TSError:⨯ 无法编译 TypeScript:index.ts:9:5 - 错误 TS2559: 键入'{名称:字符串;年龄:数字;性别:字符串; }[]' 没有 与“IPerson”类型相同的属性。

9 数据:[{name:'Steve',年龄:26,性别:'male'}, ~~~~

那么我如何将接口应用到我的Data 元素,无论它是文档数组还是简单文档。

这是 Repl.it 上上述代码的链接

Sample Playground

【问题讨论】:

  • 可能是一个简单的错误?您的数据 (myData.Data) 是一个数组,但您的界面是一个普通类型。接口定义不应该包括Data?: T[](即一个T数组而不是T)吗?或者myData 应该是IApiResponseBody&lt;IPerson[]&gt;
  • 在旁注中,我强烈建议不要添加success:true, error 等或任何表明失败的内容。使用标准的 http 代码,然后使用错误信息扩展 that 响应正文。如果您的 api 成功返回 200 和所需的 http 消息正文。这样你就可以创建一个更纯粹的 restful api。

标签: angular typescript


【解决方案1】:

因为,您想要访问可能不存在的数据。因为数据?:T[],是数据的简写:T[] |不明确的。这意味着 Data 可能包含 T[] 的值,或者它可能包含未定义的值。

所以,当你调用 myData.data[0].name 时,它​​的值可能是 steve 或者你想调用未定义数据的第一个对象的 name 属性,这是完全不可接受的,所以错误投掷。

解决方案 1:

您可以先检查数据是否存在,然后打印对象或对象的属性。

if (myData.Data) {
  console.log(myData.Data[0].name)
}

解决方案 2

或者说一定有数据,把界面中的?去掉。

export interface IApiResponseBody<T = any> {
  Error?: string;
  Message?: string;
  RowsAffected?: number;
  Success?: boolean;
  Data: T[];
  RowCount?: number;
}

直播解决方案:Repl.it

【讨论】:

  • 这就是我尝试过的,但它不允许我访问元素,然后在像这样的数据中访问 c​​onsole.log(myData.Data[0].name)
  • 似乎 t myData: IApiResponseBody 和 Data?: T[];当我打印 console.log(myData.Data) 我得到 [ { name: 'Steve', age: 26, gender: 'male' }, { name: 'Susan', age: 21, gender: 'female' }, { name: 'SteveFrank', age: 29, gender: 'male' } ] 但我无法访问任何元素或 myData.Data.length
  • 可能问题出在您的回复中。我已经在我的项目中尝试过,效果很好。如果您没有得到 console.log(myData.Data[0].name) 的响应,那是您的响应问题。因为打字稿限制了响应,但又不能阻止来。
  • 如果您查看 repl.it/@NoSoup4you2/Array-To-Object 它不适用于代码。所以不知道为什么。此代码使用静态响应来模拟它对 http 服务器的期望
  • 你能解释一下为什么我必须在访问数据之前检查的逻辑吗? if (myData.Data) { console.log(myData.Data.length) }
【解决方案2】:

你可以试试:

export interface IApiResponseBody<T = any> {
    Error?: string;
    Message?: string;
    RowsAffected?: number;
    Success?: boolean;
    [key: string]?: T | T[];
    RowCount?: number;
}

和:

let myData: IApiResponseBody<IPerson>  = {
    Success: true,
    Error: "",
    Message: "",
    RowsAffected: 9,
    Data: [{name: 'Steve', age: 26, gender : 'male'}] // or {name: 'Steve', age: 26, gender : 'male'}
    }

【讨论】:

    【解决方案3】:

    Data? 必须是 T 类型的 Array,或者如果您想允许 Array 或单个 Object,请使用 union。

    export interface IApiResponseBody<T = any> {
      Error?: string;
      Message?: string;
      RowsAffected?: number;
      Success?: boolean;
      Data?: T | T[];
      RowCount?: number;
    }
    
    export interface IPerson {
      name?: string;
      gender?: string;
      age?: number;
    }
    

    现在您可以这样做:

    let myData: IApiResponseBody<IPerson> = {
      Success: true,
      Error: "",
      Message: "",
      RowsAffected: 9,
      Data: [
        {name: 'Steve', age: 26, gender: 'male'},
        {name: 'Susan', age: 21, gender: 'female'},
        {name: 'SteveFrank', age: 29, gender: 'male'}
      ]
    }
    

    或:

    let myData: IApiResponseBody<IPerson> = {
      Success: true,
      Error: "",
      Message: "",
      RowsAffected: 9,
      Data: {name: 'Steve', age: 26, gender: 'male'}
    }
    

    【讨论】:

    • 有没有办法处理数据中的数组和/或文档?当响应中有一个以上的文档时,我的 API 将有一个数组,如果它只有一个文档,那么它不是一个数组。如果不是,我想我将不得不构建 2 个接口,然后根据 API 预期回报应用
    • 好的,尝试了您的解决方案,我收到以下错误 TSError: ⨯ Unable to compile TypeScript: index.ts:16:13 - error TS7017: Element implicitly have an 'any' type because type 'IPerson | IPerson[]' 没有索引签名。我用你的代码更新了 Playground repl.it/@NoSoup4you2/Array-To-Object
    猜你喜欢
    • 1970-01-01
    • 2021-05-05
    • 2018-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-02
    • 1970-01-01
    • 2018-11-13
    相关资源
    最近更新 更多