TypeScript:通过使用约束约束某些属性来约束现有接口

时间:2020-04-17 14:28:56

标签: typescript

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

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

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

但是,许多函数仅接受具有有效ID的Entity对象。 因此,我想介绍一个看起来像这样的新界面(不带“?”):

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

现在我的问题是我不想从原始Entity界面复制所有属性。 如何通过约束来强制扩展Entity的{​​{1}}接口?

扭转问题

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

1 个答案:

答案 0 :(得分: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'>
相关问题