【问题标题】:TypeScript: Restrict an existing interface by restricting certain properties with constraintsTypeScript:通过使用约束限制某些属性来限制现有接口
【发布时间】:2020-04-17 23:11:45
【问题描述】:

我有以下 TypeScript 接口,用作 ORM 库的数据库实体:

export interface Entity {
  id?: number;
  someColumn: string;
  someOtherValue: number;
  otherColumn: string;
}

注意可选的id 属性,它可以是实体的主键,也可以是未定义的。 如果未定义,则表示该实体在底层数据库中不存在。

但是,许多函数只接受具有有效 id 的 Entity-objects。 因此,我想介绍一个看起来像这样的新界面(没有“?”):

export interface ValidEntity {
  id: number;
  someColumn: string;
  someOtherValue: number;
  otherColumn: string;
}

现在我的问题是我不想复制原始Entity-interface 中的所有属性。 如何使用约束“扩展”Entity-interface 以强制 id 不得未定义?

反转问题

另一个问题是相反方向的同一件事。 假设我们已经有了ValidEntity 接口,并且想要创建一个Entity 接口来放宽id 属性以允许未定义。我们如何在不复制属性的情况下实现这种放松?

【问题讨论】:

    标签: typescript


    【解决方案1】:

    虽然可能有其他方式可以产生更漂亮的错误消息, 一个快速的交叉路口类型就可以了。

    export interface Entity {
      id?: number;
      someColumn: string;
      someOtherValue: number;
      otherColumn: string;
    }
    
    type ValidEntity = Entity & { id: number };
    // Alternate solution:
    // type RequiredBy<T, K extends keyof T> = Omit<T, K> & Required<Pick<T, K>>
    // type ValidEntity = RequiredBy<Entity, "id">
    
    function f(e: ValidEntity) { }
    
    let obj = {
        someColumn: "1",
        someOtherValue: 2,
        otherColumn: "3"
    }
    
    f(obj);
    // Property 'id' is missing in type '{ someColumn: string; someOtherValue: 
    // number; otherColumn: string; }' but required in type '{ id: number; } '.
    

    往相反的方向走有点棘手。基于this answer,您可以使用如下实用程序类型:

    type PartialBy<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>
    
    interface ValidEntity {
      id: number;
      someColumn: string;
      someOtherValue: number;
      otherColumn: string;
    }
    
    type Entity = PartialBy<ValidEntity, 'id'>
    

    【讨论】:

    • 效果很好,您能否也提示一下如何在相反的方向执行此操作? (我更新了原来的问题)
    • “联合类型”可能会反其道而行之,但这并不是必需的。
    • 编辑添加答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-06-26
    • 2019-10-09
    • 2019-05-09
    • 2018-12-29
    • 1970-01-01
    • 2021-09-26
    • 1970-01-01
    相关资源
    最近更新 更多