【问题标题】:How can I cast an object with fields missing to another in Typescript?如何在 Typescript 中将缺少字段的对象转换为另一个对象?
【发布时间】:2016-06-21 03:17:11
【问题描述】:

我遇到了 Typescript 接口的问题。我正在尝试将一个对象(缺少某些字段,例如 createdBy)投射到另一个对象,但我的投射不起作用。

我希望有人可以提供帮助。

这是我拥有的接口文件:

interface IWord {
    ascii?: number;
    awl570?: boolean;
    awl570Sublist?: number;
    categoryId: number;
    frequency?: number;
    groupId: number;
    lessonId: number;
    name: string;
    nawl963?: boolean;
    nawl963D?: number;
    nawl963Sfi?: number;
    nawl963U?: number;
    statusId: number;
    syllables?: string;
    toeflMcG400?: boolean;
    toeic?: boolean;
    wordForms: IWordForm[];
    wordId: number;
    createdById: number;
    createdDate: string;
    modifiedById: number;
    modifiedDate: string;
}

interface IWordForm {
    definition: string;
    posId: number;
    sampleSentences: [ISampleSentence];
    sourceId: number;
    statusId: number;
    synonyms: [ISynonym];
    wordFormId: number;
    wordId: number;
    createdById: number;
    createdDate: string;
    modifiedById: number;
    modifiedDate: string;
}

我正在尝试创建这个:

var wos.word = <IWord>{
    categoryId: 1,
    lessonId: 1,
    name: null,
    groupId: 1,
    statusId: Status.Clean,
    toefl: true,
    wordForms: <IWordForm[]>[],
    wordId: $stateParams.wordId
}

但出现以下错误:

严重性代码描述项目文件行抑制状态 错误 TS2352 既不是类型 '{ categoryId: number;课程编号:数字; 名称:空; groupId:数字; statusId:状态;托福:嘘......'也不打字 'IWord' 可分配给另一个。属性“createdById”是 缺少类型'{ categoryId:数字;课程编号:数字;名称:空; groupId:数字; statusId:状态;托福: 嘘……”管理员 C:\H\admin\admin\app\routes\words.ts 102 活动

【问题讨论】:

    标签: typescript


    【解决方案1】:

    有一个working playground example

    好吧,因为表达式word = &lt;IWord&gt;{ ...} 的赋值确实不包含createdByID、createdDate、modifedById、modifiedDate,我们应该简单地让它们为空

    interface IWord {
        ...
        createdById?: number;
        createdDate?: string;
        modifiedById?: number;
        modifiedDate?: string;
    }
    

    其他词 - 要么我们要求 Typescript 为我们检查这些不可为空......然后我们必须提供它们。或者他们可能会丢失,那么上面的解决方案就是要走的路......

    在行动中测试它here

    【讨论】:

      【解决方案2】:

      TL;DR

      var word = <IWord><any>{ name: null };
      

      回答

      正如 Radim Köhler 所指出的,如果这些字段不是您的界面工作所必需的,则将它们标记为可选在语义上是正确的。

      interface IWord {
          categoryId: number;
          groupId: number;
          lessonId: number;
          // ...
          createdById?: number; // notice the added question marks
          createdDate?: string;
          modifiedById?: number;
          modifiedDate?: string;
      }
      

      或传递未定义的默认值(就像您已经对 name 字段所做的那样):

      var word = {
          categoryId: 1,
          lessonId: 1,
          name: null,
          // ...
          createdById: undefined,
          createdDate: undefined,
          // ...
      }
      

      但是,在某些情况下,您需要创建一个没有某些字段的对象。例如。您想创建一个基本对象,然后将其传递给其他函数以添加缺失的字段。

      在这种情况下,您可以拆分界面:

      interface IWordBase {
          // some of the fields that you use internally in your function
          categoryId: number;
          groupId: number;
          lessonId: number;
          frequency?: number;
          // ...
      }
      interface IWord extends IWordBase {
          // extra fields that are required in the external code, but not necessarily required when creating an object internally
          createdById: number;
          createdDate: string;
          modifiedById: number;
          modifiedDate: string;
      }
      

      或者使用破解:

      // cast to <any> before casting to <IWord>
      var word = <IWord><any>{
          categoryId: 1,
          lessonId: 1,
          name: null
      }
      

      请记住,通过使用此 hack,您将失去编译时检查的所有好处。如果有一天你真的忘记了某个字段,编译错误将被抑制,而你会得到一个运行时错误。

      【讨论】:

      • 谢谢@zlumer 我不知道这个黑客:thumb_up:
      猜你喜欢
      • 2021-11-18
      • 2021-08-14
      • 1970-01-01
      • 2017-10-15
      • 2015-01-17
      • 2022-06-11
      • 2021-06-20
      • 2016-09-14
      • 2015-09-03
      相关资源
      最近更新 更多